前言
今天在群里看见有人发了一个CTF赛题,看了下是PHP反序列化类型的,出于好奇便做了一下,途中遇到一些坑,最后终于解决了,同时我也收获了一些自己平时没有注意过、了解掌握过的知识,因此将这个解题思路和过程记录下来,方便以后复习。
解题过程
确定漏洞类型
因为代码是直接发在群里的,我把它手动复制粘贴到了PHP文件里,方便操作。
首先看下源码
1 |
|
分析代码可知,第28号处有unserialize()
,这意味着这道题是PHP反序列化漏洞的题且我们需要传入一个携带data
参数的GET请求。
确定利用的Class
那么这里有什么可以被我们用来利用的类吗?这时我看到了class A
,发现如下代码
1 | function __toString() |
在Class A
中,有一个toString()
的方法,方法内部有我们想要的命令执行代码。
我们知道当Object与字符串比较或被执行与字符串相关操作的时候,__toString()
会被call。继续看,$data
会被执行decode_data($data)
1 | function decode_data($data){ |
重点来了,strlen($data)
代表着$data
最终是会被执行__toString()
的,那么我们更加确信,Class A
可以被我们利用实现反序列化。
构造利用Class
在__toString()
方法中,我们必须满足 if ((preg_match('/^[a-z]/i',$this->contents)))
,才能执行system()
命令。
来看下preg_match()
解释
由此可知,preg_match()
在第一次匹配到结果后,就结束匹配了。那么我们可以把代码理解为如下:
1 | function __toString() |
举个例子,如果我们$contents="<?php phpinfo() ?>"
,preg_match()
就会匹配失败,因为我们第一个字符不是字母a-z
。但如果我们的contents="a<?php phpinfo() ?>"
,这时候preg_match()
匹配到第一个字符为a,符合条件,于是不再继续检测,返回true
。
观察 system("echo $this->contents");
中有一个echo
,是输出的意思。因为我是在windows
的环境上搭建的,所以我们需要用windows
的DOS
命令。这时我想到了使用&
来执行多条命令,所以
因此我们可以构造$contents='a & echo ^<^?php ^@eval(^$_POST["leihehe"]);^?^> >>leihehe.php'
将一句话木马写入leihehe.php
文件中
注意在符号前要加上转义符^
,否则无法输出:
还有要注意单引号和双引号的问题,PHP中给变量赋值的时候,用双引号会把一些符号给翻译成PHP语言,所以我们这种符号比较多的情况,要用单引号,$_POST["leihehe"]
里面的内容用双引号。
这样我们的Class A
就构造好了。
序列化及加密(逆向思维)
那么我们应该怎么把他序列化呢?
1 | function decode_data($data){ |
通过观察,data被传入后会进行自定义的解码,最后再被反序列化。反过来,我们需要先序列化后,再按照它自定义的方式编码。
来看看他是如何解码的
1 | function decode_data($data){ |
那么他的处理过程是:
data->base64解码->chr(ord($data)+$i)->反序列化
反过来,我们构造的过程可以是:
序列化->chr(ord($data)-$i)
->base64加密->data
POC
1 |
|
赋值给$data:
可见输出了111
,这时候我们可以看到目录下已经生成了php
文件
连接菜刀即可 - 不知道为什么我的菜刀连接不上,所以直接用浏览器演示好了
总结
这道题我花了很长时间,主要是在以下坑点一直stuck:
- 没有弄清楚题目中自定义解码的过程,导致写不出来逆向的加密过程。
ord()
和chr()
不明白什么意思。ord()
是返回字符串第一个字符的ASCII
值,chr()
是把ASCII值转换为字符。 - 因为不了解
preg_match()
函数,误认为是检测所有字符,导致在这里卡了很久(自己还不知道去查一下资料..)。preg_match()
函数在匹配到第一个符合的字节后就会停止匹配。 - 对
Windows
下命令行的操作命令不熟悉,又加上不清楚preg_match()
方法,导致我以为整个variable
完全不能含有特殊符号,一直在想怎么绕过。Windows下,特殊符号前面需要加转义符^。 - 不知道有
echo 111 >>1.php
这种输出文件的写法。
总之这次收获很多,果然是要多做练习才能增加实力。