概述
本篇笔记说明 PHP 与 MySQL 交互中常见的数据请求类型、导致注入成功/失败的原因、常见的请求来源(全局变量)及利用场景,并给出绕过与防护的建议。适用于黑盒测试时对不同请求格式的分析与构造。
一、为什么“看似有注入但无法成功”?
- 黑盒测试无法直接看到原始 SQL 语句,注入成功依赖于对原 SQL 拼接方式的猜测与匹配。
- 开发者或框架对参数的处理(类型转换、转义、模板拼接)会导致常见 payload 拼接失败。
- 因此先判断请求的数据类型与封装格式至关重要。
二、常见的数据请求类型(按后端接收与拼接方式)
1. 数字型(无引号)
-- SQL 示例
SELECT * FROM news WHERE id = $id;
特点:直接拼接数字,若传入非数字可能触发类型错误或被自动转型。
绕过思路:使用不带引号的数值型 payload(例如:1 OR 1=1),注意部分框架会强制转换为整数。
2. 字符型(带单引号)
SELECT * FROM news WHERE id = '$id';
特点:常见,单引号是注入绕过的主要目标。
绕过思路:闭合单引号(' OR '1'='1)、使用十六进制或函数编码绕过过滤。
3. 搜索型(LIKE,带通配符)
SELECT * FROM news WHERE title LIKE '%$id%';
特点:参数被包含在通配符中,注入时需考虑 % 的位置与转义。
绕过思路:构造包含 % 的 payload 或利用通配符外部闭合。
4. 框架/模板型(额外括号或函数封装)
SELECT * FROM news WHERE id = ('$id');
SELECT * FROM news WHERE (id = '$id');
特点:变量包装方式复杂,直接闭合可能不起作用。
绕过思路:尝试构造能关闭所有包裹的 payload(多重闭合),或利用编码/注释技巧使外层表达式失效。
小结:绕过的核心在于「构造闭合」,尝试不同的闭合组合与编码方式。
三、常见请求来源(PHP 全局变量)
$_GET,$_POST:最常见的注入入口;$_COOKIE:持久化或跨页面注入点;$_SERVER(如HTTP_USER_AGENT,HTTP_REFERER,HTTP_HOST,HTTP_X_FORWARDED_FOR):常被记录到日志或写入数据库的字段,利用场景多样;$_FILES:文件上传名/路径若写入数据库可能产生INSERT注入。
示例:HTTP_X_FORWARDED_FOR 绕过
- 有些应用直接使用
$_SERVER['HTTP_X_FORWARDED_FOR']作为客户端 IP 并写入数据库或白名单判断,可通过伪造该头实现绕过或注入。
四、功能点与利用场景
- 用户登录/鉴权:构造 payload 绕过登录判断或篡改身份;
- IP 相关逻辑:利用伪造 IP(XFF)绕过基于 IP 的白名单或触发记录型注入(将伪造值写入日志/数据库);
- 文件上传流程:上传文件名或路径写入数据库时可触发
INSERT注入; - 日志/审计字段:User-Agent、Referer 等头部常被写入日志,适合盲注或链式利用。
五、数据请求格式(对注入的影响)
- 统一格式(JSON):后端解析 JSON 后再带入 SQL,可能改变原始拼接(需抓包查看解析节点)。
- 编码/加密(如 Base64):传输前编码,后端解码再使用,注入点需针对解码后的内容构造 payload。
测试技巧:在黑盒场景下,尝试发送简单的 JSON/编码变体,并观察响应差异与错误信息,确定解码与解析流程。
六、检测流程
- 确认输入位置与请求类型(GET/POST/JSON/COOKIE/HEADER/FILES);
- 判断后端对参数的处理(是否强类型转换、是否去除了引号);
- 使用最小变体进行闭合测试(如
+','、' OR '1'='1、%25编码等); - 若无显性回显,切换盲注方法(布尔型/时间型);
- 利用日志/头/上传点进行链式利用。
七、防护建议
- 使用参数化查询(Prepared Statements)或 ORM,避免字符串拼接;
- 严格校验并转换输入类型(对数字使用类型检查);
- 对所有写入日志/数据库的头部与文件名进行转义与限制长度;
- 最小权限原则:数据库用户只保留必要权限;
- 对外部头部(如 X-Forwarded-For)不直接信任,并在可信层做额外验证。
八、payload
- 数字型:
id=1 OR 1=1。 - 字符型:
id=' OR '1'='1' --。 - JSON 示例:
{"id":"1' OR '1'='1"}(视后端解析而定)。