序列化是对象串行化,对象是一种在内存中存储的数据类型,寿命是随生成该对象的程序的终止而终止,为了持久使用对象的状态,将其通过serialize()函数进行序列化为一行字符串保存为文件,使用时再用unserialize()反序列化为对象。
serialize 将对象格式化成有序的字符串
unserialize 将字符串还原成原来的对象
Php在反序列化时,底层代码是以;作为字段的分隔,以 } 作为结尾,并且是根据长度判断内容的 ,同时反序列化的过程中必须严格按照序列化规则才能成功实现反序列化 。
先来做个小实验:

序列化lt对象并输出,s代表类型,后边的数字代表长度,当使用正则来替换掉admin时,会发现:

发现只有admin变成了hacker,但长度没变,此时如果再将其反序列化时回因为长度无法匹配而报错。

这个是输出没有替换之前的对象,可以正常输出。

当输出替换之后的数据时回显false,此时猜想一下,如果我们自行让其匹配会发生什么变化。

我们使多出的长度刚好可以与impo后边的字符串长度匹配,需要41个admin。

此时可以发现,md51和md52的值已经改变,逃逸成功。
字符逃逸CTF例题的思路,改变序列化字符串中某一值的长度,从而导致反序列化漏洞,所以在代码审计时如果发现了正则表达式的搜索和替换,并且需要修改一个序列化字符串中的值时可以往这方面考虑,但要注意几个点:
打开后发现一个登录框,盲猜有注册页面,访问/register.php。
注册后登录,之后没有其他的提示,尝试sql注入和文件上传无果。
扫一下目录发现www.zip源码泄露,开始审计。
发现profile.php中存在任意文件读取。

又发现flag在config.php中。

理清思路,利用任意文件读取漏洞,读取config.php文件即可。
因为photo是$profile中的值,跟着其走一下。
首先跳到了show_profile。

然后再到filter,是一个正则匹配替换,匹配之后再返回去。

继续又调用了父类的select函数。

Sql语句,将表中的内容取出来,所以查询有关表的插入语句。

发现了update,继续找哪里有update的利用点,在updata.php中发现其利用点。

Profile的值是通过POST传入,但photo的值是md5哈希编码后的值,无法直接控制。
最后想到了在中间有一段匹配替换,可以利用字符串逃逸,直接更改profile的值。
刚好替换的where和hacker长度相差1。

构造后,将需要的地方截取下来,然后计算其长度。
直接传入后,一直无法成功,之后发现nickname存在过滤。

可以利用数组绕过。
因为nickname传入为数组,改一下payload。
"};s:5:“photo”;s:10:“config.php”;}长度变成了34。
Paylaod:
wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}
注意传入时nickname变成数组形式。

最后信息是以图片的形式返回的,所以flag在图片的编码里。

base64解码得到flag。
先本地试一下,在这里插入代码片和上边一样。

然后将php变成空格试一下。

在这里可以理解一下,字符串缩短的方法是让本来的前边一部分代替我们删除的字符,然后在让其提前闭合,主要还是前后可以刚好匹配。
合适的例题没找的,不然就是太简单,不然就是太难,之后再补充。