PHP安全:变量的前世今生
字数 1469 2025-08-15 21:31:50
PHP变量安全全面指南
变量生命周期与安全风险
PHP变量的生命周期可分为四个阶段,每个阶段都存在特定的安全风险:
- 传入参数阶段
- 变量生成阶段
- 变量处理阶段
- 变量储存阶段
Part1: 传入参数安全
1. 畸形HTTP方法绕过
- WAF通常只检查标准HTTP方法(POST/GET)
- 可使用任意非保留字作为HTTP方法:
等效于:ABCDEFG /lab_value/get.php?num_value=hhh HTTP/1.1GET /lab_value/get.php?num_value=hhh HTTP/1.1
2. URL-WAF绕过技术
HPP参数污染
- PHP中间件会以最后一个重复参数为准
- 示例:
/?password=admin&&pasword=' order by 1--+
截断绕过
- 长度截断:WAF可能只检查前N个字符
- 终止符截断:使用
%00截断检查
数据分裂绕过
-
分块编码传输(Transfer-Encoding: chunked)
- 消息体由多个块组成,每个块包含:
- 数据字节数(十六进制)
- CRLF
- 数据本身
- 块CRLF结束
- 最后一块为0字节大小
- 消息体由多个块组成,每个块包含:
-
Pipeline绕过(Connection: keep-alive)
- 保持连接不中断,合并多次请求
3. 参数数据类型绕过
PHP接受参数时的特殊解析规则:
| 输入内容 | PHP解析结果 |
|---|---|
| 空格num_value | num_value |
| num[value | num_value |
| num.value | num_value |
| Num_value | 报错(大小写敏感) |
| num value | num_value |
| num_value | num_value |
| /?num_value[]=xxx | 传入数组 |
特殊技巧:
- 传入数组可绕过md5检查:
md5(aaa[]) === md5(bbb[])
4. 编码问题
- 双重URL编码:
%27→%2527 - URL解码自动过滤%:
sel%ect→select - Base64解码要求字符数为3的倍数
Part2: 变量生成安全
1. REQUEST变量获取
$_REQUEST同时获取GET和POST参数- 可同时发送GET和POST请求绕过部分WAF
2. extract()函数风险
- 将数组键值对转换为变量
- 可能导致变量覆盖,常用于CTF中覆盖白名单
3. 反序列化安全
unserialize()处理参数实例化为对象- PHP特殊性质:十六进制字符串等价
var_dump("\x66\x6c\x61\x67" == "flag"); // true - 生成十六进制字符串脚本:
<?php $string = 'flag'; $arr = str_split(bin2hex($string), 2); foreach ($arr as $value) { print('\x'.$value); } // 输出: \x66\x6c\x61\x67 ?>
4. md5二进制输出
md5(xxx, true)输出16位二进制数据- 特殊值
ffifdyop会被解码为类似' or 1=1的结构
Part3: 变量处理安全
1. 弱类型比较问题
PHP弱类型比较(==)的典型问题:
var_dump("abcd" == 0); // true
var_dump("1abcd" == 1); // true
var_dump("abcd1" == 1); // false
var_dump(abdc1 == 0); // true (报错)
var_dump(False == 0); // true
var_dump("abcd1" == 0); // true
var_dump("0e123456" == "0e888888"); // true (科学计数法)
2. 正则匹配绕过
异或绕过
- PHP允许字符串按ASCII编码异或
- 异或规则:
- 值不同 → 1
- 值相同 → 0
- 示例:
3 xor 2 == 1 2 xor 2 == 0
PCRE回溯次数绕过
- 带有通配符(*或?)的正则可能回溯
- 当回溯次数超过限制(默认100万)返回false
- 使用
===比较可避免绕过
Part4: 变量储存安全
1. 命名空间利用
- 在回调函数前加
\可绕过多数WAF - 示例:
\system($_GET['cmd']);
2. 自定义函数绕过
- 通过函数拼接、动态调用绕过静态检查
- 示例:
function x($a,$b){ call_user_func_array($a,$b); } x('assert',array($_POST['a'])); // 或拼接函数名 $y = 'a' . 'ssert';
防御建议
- 始终使用
===进行严格比较 - 禁用危险函数如
extract()、assert() - 对用户输入进行严格过滤和类型检查
- 使用最新版PHP并保持更新
- 避免直接反序列化用户输入
- 对正则表达式进行性能优化,防止回溯攻击
- 使用命名空间时注意权限控制
- 对文件操作函数进行路径检查和过滤