原创 Xenny 合天智汇
快睡的时候,打开B站发现有位用户留言,大意就是让我帮忙看一道题,正好当时有空,于是就打开了他发的链接,代码如下
很明显是一道PHP代码审计的题目,而且只需要绕过第三行的if即可进行任意命令执行。
解决思路
看了代码之后觉得是道普通的题目,对于/a-zA-Z/这个正则表达式,我们可以利用PHP动态函数的特性,构造出字符串即可。
对于想要的字符串,我们可以通过以下三种方式来构造:
1. 异或
对于PHP中的字符串,两个字符串异或的结果是将两个字符串逐位异或,返回一个新字符串。那么我们便可以使用此特性进行构造。
例如我们需要构造phpinfo,则可以用脚本得到('0302181', '@[@[_^^')这两个字符串,脚本如下:
其中valid是可用的字符,answer是我们需要构造的字符串。那么我们得到了这个字符串,又该如何去执行呢。我们可以通过一个变量存储两字符串异或后的值,再让这个变量进行动态函数执行即可,而变量的话因为PHP的变量命名规则和C语言相同,可以使用下划线进行命名,如下:
2. 取反构造
和第一种类似,都是基于PHP字符串位运算的特点(会逐位进行位运算)。而取反构造某些情况比异或构造要方便,因为异或的情况某些字符是无法直接通过其他字符进行异或构造的,而取反却可以利用汉字或者其他特殊字符进行构造(不会有题目会限制某个汉字吧)。比如字母s我们可以通过~('和'{2})得到。而这个时候如果要用异或去构造的话,你得找到两个异或值为s的特殊字符。
取反构造的脚本和异或构造类似,在此不再给出。
3. 自增构造
`++'a' == 'b'
`
这个特点是利用了PHP是弱类型语言的特性,在对变量进行操作的时候,PHP会隐式的转换其变量类型,很多代码审计的题目也是利用了这一特性。
遇到障碍
有了上面的思路后,而且也成功执行了phpinfo(),下一步是不是就可以直接构造命令执行函数去进行读取文件,当时我也是这么想的,于是我构造了passthru(), system(), shell_exec(), exec()等函数,都受到了阻碍,没有回显,通过进一步的调试之后发现是禁用了这些函数(通过在函数后面加一个打印函数观察是否执行)。
在这里我停留了很久,试过打印$GLOBALS等都没有任何有用的信息。最后通过使用glob()函数进行目录扫描,发现了flag.php文件,以及file_get_contents()进行获取,最终的payload如下
?mess=$_="`0123"^"?`~``";${$_}[_](${$_}[__]);%=xxx%>的方式,那么在PHP中是否也有这种方式呢,答案是肯定的,PHP中的?=xxx?>就可以将一个变量输出,那么如果使用它呢,你只需要构造如下的payload
$_="xxx";?>?=$_?>
这样就可以将变量$_里面的内容打印到屏幕上,而且关键的是这个输出方式默认是开启的,管理员很容易就忽视这个选项。所以在做题时不妨一试。
2. 其他的命令执行方式
当system,passthru等不能用时,网上会告诉你可以使用popen,proc_open这些管道命令去进行执行命令,当然这没有问题,而这里我向你介绍一种新方式,使用反引号,在PHP中,被两个反引号括起来的内容将会作为shell命令执行,并将输出信息返回,所以你可以构造下面的payload进行命令执行
$_=`ls`;
3. 不能使用数字字母的命令执行
当不能使用字母数字时,当然你可以使用上述的方式构造字符串进行执行,但是这里提供一些新东西,对于linux中的shell是支持正则表达式的,当你忘记某些字符时可以通过? % *来代替,经过测试,这里的匹配方式也是按照顺序进行匹配,所以你可以查看你的linux中/bin目录下面的顺序,来获取一些可以使用的命令,比如
/???/??? => /bin/cat
那么这样的话,如果要获取/var/www/html/index.php(你得感谢apache默认目录如此之深),则可以直接使用
/???/??? /???/???/????/?????.???
来获取
总结
这篇文章只是针对这道题而延展出的一些东西,在真正做题时,情况可能更加复杂,例如限制长度,限制参数等等情况,而我们的做法也不可能千篇一律,可能某些时候我们甚至会用到一些CVE漏洞。而本篇文章只是告诉读者一些可能以前没有见过的新东西。
那么本篇文章就到此结束了。
如果想更多系统的学习CTF,可点击“http://www.hetianlab.com/pages/CTFLaboratory.jsp”,进入CTF实验室学习,里面涵盖了6个题目类型系统的学习路径和实操环境。
声明:笔者初衷用于分享与普及网络知识,若读者因此作出任何危害网络安全行为后果自负,与合天智汇及原作者无关!
标签: 合天智汇
还木有评论哦,快来抢沙发吧~