嵌套的反序化问题
(源于我做题时的一个疑问)
直接说结果:
如果一个序列类似:
O:4:”User”:2:{s:8:”username”;i:123;s:8:”password”;O:4:”evil”:1:{s:4:”hint”;N;}}
这种“类中有类”的格式,进行unserialize反序化操作,
是否合法?反序化外层后,字符串中的“O:4:”evil”:1:{s:4:”hint”;N;}”是否也会反序化(还是保留)?
答案:合法,并且所有O开头的内容都会被反序化。(相当于先反序化最外层,再逐个检索所有的实参和形参的位置,若其本来格式还可以反序化,则继续反序化,直到没有可以反序化的为止)
下面进行大体的解释:
为了方便解释,整个解释都会以下面的两个类为基础——
首先,php并不支持“类的嵌套”,也就是说下图这种格式是不合法的,所以我说的“嵌套”其实只是反序化比较像在class里构建了一个class——
这里就要先纠正我以前一个误区——
O:4:”User”:2:{s:8:”username”;i:123;s:8:”password”;i:456}
这句话反序化以后并不是等价于class User这个类,
它单纯等价于new User(username=123,password=456);的过程
所以O:4:”User”:2:{s:8:”username”;i:123;s:8:”password”;O:4:”evil”:1:{s:4:”hint”;N;}}
其实等价于new User(username=123,password=(new evil));(或者更标准的是new User(123,new evil);),这样就会好理解很多。
但是使用的时候,需要实现某一个需要反序化的部分“整个替换”
比如O:4:”User”:2:{s:2:”p1”;i:p2;s:2:”p3”;i:p4}
想要把O:4:”evil”:1:{s:4:”hint”;N;}替换上去,让其触发evil类,
能替换的部分分别为——
s:2:”p1”
i:p2
s:2:”p3”
i:p4
不能有多余的s或i残留,所以最好在字符逃逸漏洞中使用,参考——https://blog.csdn.net/dengyu810/article/details/103213750