这个文章啊,前前后后改了三次了,每次是做题忘记了,然后复习,然后又有新的想法,便写下来了,
2021.4.5第三次修改
1.通用套路:
这里错了,后面闭合不一定总是;}
还有可能是}
具体看,
字符串的化,结尾是由分号的,其他如 对象,就不是分号结尾,直接是 右括号结尾
要记住的是: 字符逃逸的题,一定是 先 serialize(),然后 过滤(变多or变少),然后 unserialize() 。从而实现逃逸
不管字符增多 or 字符减少,套路一样,就是我们构造的都是 反序列化之后的字符串,比如s:4:"name";s:8:"flag.php"
。这样的,并且,我们在当参数输入进程序的时候,前面 和 后面 都要闭合
,比如:";s:4:"name";s:8:"flag.php";}
。这样,不给别人添麻烦!
1. 字符数变多的时候
?name=hello
,然后我们要进行字符逃逸,假设过滤会把6
变多,变成xx
,我们输入?name=66666";s:4:"name";s:8:"flag.php";}
,然后serialize之后会变成这样a:2:{s:4:"name";s:53:"xxxxxxxxxxxxxxxxxxxxxx ";s:4:"name";s:8:"flag.php";}";}
,(个数不对,瞎写的,)。然后让xxxxx
个数刚好是53
个。这就实现了字符逃逸,
将我们构造的 反序列化字符串逃逸出来了,,最后过滤完,会进行反序列化,就达到我们的目的了。
2. 字符数变少的时候:
?name=adam&sign=hello
,然后我们要进行字符逃逸,假设过滤会把666
变多,变成xx
,我们输入?name=66666666666666 & sign=";s:4:"name";s:8:"flag.php";}
。serialize()之后变成s:4:"name";s:23:"xxxxx";s:4:"sign":s:25:"";s:4:"name";s:8:"flag.php";} ";}
。将 我们构造的反序列化的字符串的序列化之后的一些信息给吃掉了,所以我们的反序列化字符串就逃逸了,然后进行unserialize(),实现目的
解释
缩水,变少。我们在缩水变量的后一个变量生成多余字符 把多余的字符 往前推。 从而增多字符个数,使得 缩水后 总的 === 刚开始的时候的
详细解释
我们想要构造成什么东西,就在相应的变量的位置上去构造相应的序列化之后的字符串(记得该闭合的都给闭合了)。当然,php会把他们再一次序列化,不过没事,我们就需要让前一个变量字符串数量缩水。从而把后面的一些不需要的字符给吸收了就好了。剩下我们输入时的那些。刚好反序列化出来我们想要的数据
2.基础知识和一些特性
知识
字符串逃逸是 一种闭合思想,类似于xss和sql万能密码一样,构造,然后闭合,绕过
序列化的值以 ; 作为字段分隔。结尾是 } 结束,并且是根据 长度 判断内容的
特性
PHP在反序列化的时候,类中不存在的属性也会进行反序列化。
当长度不对应的时候会报错。
分为两类:
- 过滤后字符变多
- 过滤后字符变少
1.过滤后字符变多
这是正常的时候
<?php
function text($str){
return str_replace