php反序列化字符串逃逸
前言:
反序列化确实有很多内容需要去学,前段时间学习的反序列化确实不够用
基础知识:
1.php在反序列化时,对类中不存在的属性也会进行反序列化
1 |
|
2.php在反序列化时,底层代码是以;作为字段的分割,以}作为结果(字符串除外),并且是根据长度判断内容的
3.对于类似这种O:1:”A”:2:{s:1:”a”;s:3:”123”;s:1:”b”;s:9:”xianyu123”;}s:1:”c”;s:2:”yes”;也是能够正常反序列化的,即使s:2:”yes”的长度不匹配也不影响。说明php在反序列化的时候只要求一个反序列化字符串块合法即可,当然得是第一个字符串块。
漏洞产生原因
序列化的字符串在经过过滤函数不正确的处理而导致对象注入,因为先进行了序列化,再进行过滤,那么就有可能会产生此漏洞。
实战
1 |
|
首先看看原本输出的内容:
1 | string(39) "a:2:{i:0;s:5:"admin";i:1;s:6:"mypass";}" |
1 | $username = "ggggyu123cccccccccccccccccccc\";i:1;s:6:\"123456\";}"; |
1 | string(84) "a:2:{i:0;s:49:"ggggyu123cccccccccccccccccccc";i:1;s:6:"123456";}";i:1;s:6:"mypass";}" |
此时成功更改密码,刚刚理解了一下,其实原理很简单,先理解以下几点:
1.对应前一个序列化内容s:49这里说第一个变量的值有49个字符长度,那么接下来就会一直读取49个长度,如果少于或者大于都会报错导致读取不了
2.经过filter,我们发现一个c被替换成两个b了,但是依旧字符串长度为49个,但是我们原本在username里面的内容是变多了,这样我们后面输入的i:1;s:6:”123456”;}就逃逸出来了
3.我们知道序列化是以读到}为终止的,所以此时密码就被修改为123456,因为后面的mypass那些已经被舍弃掉了
php反序列化字符串逃逸