目录
一、审计流程
目标确定
| 来源 | 获取源码方式 |
|---|
| 开源 CMS | GitHub 下载 / 官方仓库 |
| 闭源站点 | php://filter 读源码(见 04/05 章) |
| 框架应用 | Composer 依赖 + 业务代码 |
| CTF | 题目直接给源码 |
审计五步
1. 摸结构 → 目录结构、入口文件(index.php)、路由(.htaccess/Nginx conf)
2. 找输入 → $_GET/$_POST/$_COOKIE/$_SERVER/$_FILES 全量标注
3. 追污点 → 输入流向危险函数(system/eval/include/query)
4. 挖入口 → 公共组件:登录、上传、下载、搜索、导出、导入
5. 验证 → 本地复现(php -S + 同版本)→ 确认可利用
二、漏洞模式速查表
| 漏洞 | 典型代码 | 攻击载荷 |
|---|
| SQL 注入 | "SELECT * FROM u WHERE id=" . $_GET['id'] | 1 or 1=1 |
| XSS | echo $_GET['name'] | <script>alert(1)</script> |
| 命令执行 | system("ping " . $_GET['ip']) | ;id %0a |
| 代码执行 | eval($_POST['code']) | system('id'); |
| 文件包含 | include($_GET['file']) | php://filter/... |
| 文件读取 | file_get_contents($_GET['f']) | /etc/passwd |
| 文件写入 | file_put_contents($_GET['f'], $_POST['c']) | 写 WebShell |
| 上传 | move_uploaded_file($tmp, $dir . $name) | 恶意扩展/图片马 |
| 反序列化 | unserialize($_COOKIE['data']) | POP 链 |
| SSRF | file_get_contents($_GET['url']) | 内网探测 |
| XXE | simplexml_load_string($_POST['xml']) | 外部实体读文件 |
| 路径穿越 | readfile("data/" . $_GET['name']) | ../../etc/passwd |
| 弱比较 | if ($_GET['pw'] == $pw) | 0 / 0e / 数组 |
三、输入与输出追踪
输入标注
<?php
// 所有输入点
$id = $_GET['id']; // GET
$user = $_POST['user']; // POST
$sid = $_COOKIE['sid']; // Cookie
$ip = $_SERVER['REMOTE_ADDR']; // 不可伪造
$xff = $_SERVER['HTTP_X_FORWARDED_FOR']; // 可伪造!
$ua = $_SERVER['HTTP_USER_AGENT']; // 可伪造
$refer = $_SERVER['HTTP_REFERER']; // 可伪造
$all = $_REQUEST['x']; // GET+POST+Cookie
$json = file_get_contents("php://input"); // 原始 body
?>
污点追踪例子
<?php
// 案例:看似无害,实则可控
$op = $_GET['op'];
$file = "cache/" . $op; // 污点进路径
include($file . ".php"); // → LFI(用 filter 绕过后缀)
?>
<?php
// 案例:二次传入
$name = trim($_POST['name']); // 清理? 只去空格
$name = htmlspecialchars($name); // 转义? 只防 HTML
include("tpl/" . $name); // 但进入文件包含 → 转义无效
?>
审计要点:每个”清理”函数只对特定上下文有效。htmlspecialchars 防 XSS 不防 SQLi,addslashes 防 SQLi 不防 LFI,intval 防注入但截断语义不同。
四、高危函数grep清单
命令/代码执行
grep -rnE "eval\(|assert\(|system\(|exec\(|shell_exec|passthru|popen|proc_open|create_function|preg_replace.*\/e" .
文件操作
grep -rnE "include|require|file_get_contents|file_put_contents|fopen|unlink|readfile|move_uploaded_file|unserialize|phar://" .
数据库
grep -rnE "query\(|mysql_|mysqli_|PDO.*query" .
其他
grep -rnE "shell_exec|`\s*\$|mail\(|putenv|proc_open|pcntl_exec" .
输入点标注
grep -rnE '\$_GET|\$_POST|\$_REQUEST|\$_COOKIE|\$_FILES|php://input' .
五、框架审计要点
通用框架文件
| 框架 | 配置文件 | 路由 | 常用漏洞点 |
|---|
| ThinkPHP | .env / config/ | route/ | 反序列化、SQLi |
| Laravel | .env | routes/web.php | 反序列化(PHPGGC)、debug 模式 |
| Symfony | .env | config/routes | 反序列化 |
| WordPress | wp-config.php | 插件钩子 | 插件漏洞、上传 |
| 自研框架 | 入口 index.php | 手工 | 无统一防护,漏洞密度高 |
框架特有的坑
| 坑 | 说明 |
|---|
| debug 模式开启 | 异常页泄露路径/环境变量 → 信息收集 |
| 全局过滤失效 | 框架过滤只对绑定参数生效,原生函数调用不受保护 |
| 反序列化入口多 | Cookie/session/cache 常存对象 |
| 依赖组件漏洞 | Composer 依赖老版本 → 直接用 PHPGGC |
| 模板注入 | 用户输入进模板变量 → SSTI(框架渲染) |
<?php
// 框架内绕过过滤的典型写法
DB::query("SELECT * FROM user WHERE id=" . $request->get('id')); // 原生拼接绕过 ORM 参数绑定
?>
六、自动化工具链
| 工具 | 用途 |
|---|
phpstan / psalm | 静态分析(类型/死代码) |
RIPS(停维护) | PHP 污点分析经典 |
Fortify SCA | 商业级 |
grep 流 | 见四节清单 |
PHPGGC | 反序列化 gadget 生成 |
php_filter_chain_generator | filter 链 RCE 生成 |
semgrep | 自定义规则污点追踪 |
# semgrep 自定义规则示例(找 eval 用户输入)
semgrep --lang php -e 'eval($INPUT)' --validate
本地复现环境
# 目标版本复现
sudo apt install php7.4-cli # 或 php8.1-cli
php -S 127.0.0.1:8080 -t ./target_src
php -r 'var_dump("1e3" == 1);' # 验证弱类型行为
七、红队视角总结
| 阶段 | 产出 |
|---|
| 摸结构 | 入口文件、路由、配置、框架版本 |
| 找输入 | 输入点清单(GET/POST/Cookie/头/body) |
| 追污点 | 输入 → 危险函数路径图 |
| 挖入口 | 登录/上传/搜索/导出等公共组件 |
| 验证 | 本地复现确认 |
优先级:RCE 类(命令/代码执行、反序列化、LFI→RCE)> 文件类(上传/读写)> 数据类(SQLi/SSRF/XXE)> 输出类(XSS)。
审计完的交付:漏洞清单(入口、payload、影响、修复建议),对齐红队报告标准。
返回 PHP 总目录 | 前端基础总目录