1.漏洞产生的原因
#### 正常的反序列化语句是这样的
$a='a:2:{s:8:"username";s:7:"dimpl3s";s:8:"password";s:6:"abcdef";}';
但是如果写成这样
$b='a:2:{s:8:"username";s:7:"dimpl3s";s:8:"password";s:6:"123456";}s:8:"password";s:6:"abcde";}';
也可以正常的编译, 而且下面一条语句的结果是 password=“123456” 而不是abcde
结果
这就说明一个问题,在反序列化的时候,只要求第一个序列化字符串合法就行,换我个理解,就是反序列话时,他会从前往后读取,当读取第一个合法的序列化的字符串时,就会反序列化。
### 当过滤用户输入参数的时候,如果先序列化再对序列化过后的字符串进行过滤,而且在过滤的过程中会导致原本的长度改变,就可能造成序列化对象注入漏洞。
此处参考别人的代码:
可以看到,这里过滤函数将原来的x换成了zz,但是长度却超过了原来的长度 ,但是原来长度的数字时没变的,这就导致报错。但是试想一下,如果这里的密码是可控的,然后我们输入字符
的时候带入双引号和} 会怎么样呢? 看如下代码
结果
第一排是我们构造的东西序列化过后的值,
第二排是序列化过后的值进行过滤过后的值,可以看到,此时由于x换成了z,而前面读40的时候正好会读到最后一个x,从而使我们输入的新对象得以注入,而且得到正常的反序列化。
第三排是反序列化过后的到的值,此时原本的aaaaaa的值已经被我们覆盖。
二:实例分析
根据上面的原因可知,产生漏洞最直接的原因是因为序列化过后的字符串被过滤的时长度发生变化, 根据这个这个原因,我们就可以把漏洞分为 长度变长,和长度变短两种情况,注意! 如果长度不变的话,不会引起漏洞产生。
(1) 长度变短。
题目: 安洵杯2019 easy_serialize_php // 在https://buuoj.cn/这个靶场里又复现
源码: