buu25
[EIS 2019]EzPOP
找到一个危险函数根据此函数往前看看是否能传值进去这里有个exit(),好像不会执行后面data的内容,这里待会需要想办法绕过,但是首先需要弄懂将值传入的链
data首先可能会经过一个压缩的操作为了不让data发生改变,我们就需要将data_compress设为0
接下来会经过一个serialize的函数操作,如果为数字,那么就会返回string的data,那我们可以先让我们data会string类型,后面因为serialize()可以看成是一个函数的执行,并且serialize可以由我们直接赋值,这里可以使用strval函数。
向上是set函数没传入这些值,其中value就是对应我们后面的data
往上对应来自于class A中的content中,而这里的store需要赋值为classB中,不然找不到set方法
在往上看到来自于cleanContents中的cache,这个在前面的定义中没有看到,所以我们可以直接自己定义一下这个变量,看到下面还有一个json_encode为了防止被json_encode,我们这里还需要将complete设置为0这样子的话就可以避免被json_encode
最后再向上来到construct这里,这里有对store进行赋值,这里需要赋值为new B
现在整理一下编写pop链条:
|
现在的难点在于我们写入的内容前面有一个exit()这样的话,我们写入的内容将不会被执行,参考
https://www.leavesongs.com/PENETRATION/php-filter-magic.html
这里介绍的方法是这样的:先使用php://filter/wtrite=convert.base64.decode/resource=./uploads/伪协议,对原本文件中的内容进行base64编码后的读取,除掉那些<?的特殊字符,我们只会对phpexit进行base64编码,我们传入的内容也需要是base64加密,但是我们可以多传入几个字符,打乱前面的加密
base64加密方式:
第一步,将待转换的字符串每三个字节分为一组,每个字节占8bit,那么共有24个二进制位。
第二步,将上面的24个二进制位每6个一组,共分为4组。
第三步,在每组前面添加两个0,每组由6个变为8个二进制位,总共32个二进制位,即四个字节。
第四步,根据Base64编码对照表(见下图)获得对应的值。反过来,base64解码时,一定是4个有效字节为一组进行解码
所以说这里要跟踪一下content传入的值,可以发现最终传入的值为第一个数组的键值,以及嵌套后的数组的键值
拼接以后即变成,因为接下来由于我们使用的伪协议的decode打开,所以前面这些将被base64解密回去,变成乱码 exit就消失了
phpexit111 这里是一句话木马 |
接下来写一下pop链:
|
小结:
这道题的坑点还挺多的
1.存在许多可能改变data的函数,但是都可以绕过
2.传入的数组需要为双重数组,具体是为什么可以在phpstorm中调试一下,并且我们的内容的键名还必须是他要求的那几个才会被识别进入content
3.exit的绕过需要了解base64的加密方式,然后后面的payload,在我们传入的时候后面需要再添加几个字母来补齐,防止前面的内容在解密的时候被吃掉