概念
了解字符逃逸前需要的补充
知识点一
知识点二
字符逃逸—字符增加
字符逃逸—字符减少
概念
在学PHP字符串逃逸之前先了解一下原理是什么,字符串逃逸的原理其实就是让字符串变成可以执行的序列化代码。在序列化和反序列化这个中间过程中,序列化字符增加或减少后,再去反序列化可能会发生属性逃逸。
额,可能会有点不太理解,没关系,进一步解释
了解字符逃逸前需要的补充
一般我们进行反序列化时候常规方式是这样的
<?php
class test{
public $aumg = '111';
public $id = 'aaasystem();';
}
$a = serialize(new test());
echo $a;
var_dump(unserialize($a));
?>
先去实例化一下对象类,然后进行序列化/反序列化的操作,输出结果分别如下:
O:4:"test":2:{s:4:"aumg";s:3:"111";s:2:"id";s:12:"aaasystem();";}object(test)#1 (2) {
["aumg"]=>
string(3) "111"
["id"]=>
string(12) "aaasystem();"
}
那么正常的是这样进行一个操作,那么我们就不正常,我们就想让这个test() 类去反序列化的时候输出点其他的类属性,就比如我想要反序列化输出时加一个类属性,或者直接修改存在的类属性,那么需要怎么操作呢❓可以先想一想,再来继续往下看。
一般字符串逃逸会有一个类似于替换字符串的功能函数,例如php中的str_replace(),以下面的代码来展开讲解:
讲解逃逸前先来补充一下知识点:
知识点一
:
举例
<?php
class test{
public $id = 'lslsls';
public $ss = '123';
}
$a = serialize(new test());
$b = str_replace('ls','pwd',$a);
var_dump($b);
?>
这里使用var_dump()方法来抑制报错,错误直接返回false,正确直接输出反序列
为了方便观察这里直接以最简单的方式进行演示,我预先在类中设定了一个共有属性$id
值为字符串ls,这段代码很容易理解,就不解释了,运行一下,输出结果为:
string(59) "O:4:"test":2:{s:2:"id";s:6:"pwdpwdpwd";s:2:"ss";s:3:"123";}"
输出了一个总共有59个字符拼接成的序列化字符串,并且发现类的$id
属性的值已经被字符串pwd进行了替换,序列化出来的结果再去进行反序列化,能不能执行呢❓思考一下。
进行反序列化:
<?php
class test{
public $id = 'lslsls';
public $ss = '123';
}
$a = serialize(new test());
$b = str_replace('ls','pwd',$a);
$c = unserialize($b);
var_dump($c);
?>
肯定不能,输出结果为:
bool(false)
因为序列化之后的结构是这样的:
O:类名的长度:类名:类中属性个数:{第一个类属性的种类:类属值的字符长度:"类属性名称";第一个类属性值的种类:类属值的字符长度:"类属性值名称";}
为什么反序列化不出来对比一下哪里出错了❓
可以发现类属性的值与他对应的字符串长度不一致,本应为9
,但是反序列化时候是6
,所以输出的值为false
知识点二
:
还是以下面的代码举例:
<?php
class test{
public $id = 'lslsls';
public $ss = '123';
}
$a = serialize(new test());
var_dump($a);
?>
输出结果为:
string(56) "O:4:"test":2:{s:2:"id";s:6:"lslsls";s:2:"ss";s:3:"123";}"
这个一定可以反序列化,但是我们用这个序列化的结果再去构造一下:
O:4:"test":2:{s:2:"id";s:6:"lslsls";s:2:"ss";s:3:"123";}:s:4:"wang";s:1:"q";};
想一想这个反序列化后得到的结果会是什么❓
反序列化代码:
<?php
class test{
public $id = 'lslsls';
public $ss = '123';
}
$a = serialize(new test());
$b = 'O:4:"test":2:{s:2:"id";s:6:"lslsls";s:2:"ss";s:3:"123";}:s:4:"wang";s:1:"q";}';
$c = unserialize($b);
var_dump($c);
输出结果为:
object(test)#1 (2) {
["id"]=>
string(6) "lslsls"
["ss"]=>
string(3) "123"
}
可以看到,我们构造的:s:4:"wang";s:1:"q";}
并没有被反序列化,这是为什么呢❓
这是因为在序列化之后的结果,也就是O:4:"test":2{s:2:"id";s:6:"lslsls";s:2:"ss";s:3:"456";}
这一部分如果没有一点差错,结构完整,可以被反序列化的情况下;}
就是反序列化的结束。
当然,这里并不是说只要是;}
就是反序列化的结束,可以举一个例子:
O:4:"test":2:{s:2:"id";s:4:"ls;}";s:2:"ss";s:3:"456";}
假如这个序列化的结果成立,那么这种说法(;}
就是反序列化的结束) 就是错误的,为什么这样说,因为如果不能反序列化(输出结果如果为bool(false)
),证明到了第一个$id
类属性值这个地方的;}
反序列化就已经不在进行了,因为序列化结构已经出错了,这里不懂的可以向上翻,上面介绍了这是为什么;那么如果不出错,则就是直接可以反序列化出来所有属性(包括类属性ss
和提所对应的值123
)
完整代码如下:
<?php
class test{
public $id = 'ls;}';
public $ss = '123';
}
serialize(new test());
$b = 'O:4:"test":2:{s:2:"id";s:4:"ls;}";s:2:"ss";s:3:"456";}';
$c = unserialize($b);
var_dump($c);
运行结果为:
object(test)#1 (2) {
["id"]=>
string(4) "ls;}"
["ss"]=>
string(3) "456"
}
这里就不再陈述为什么没有反序列化出来ss
为123
的原因了,可以自己去动手试一下序列化类之后,在反序列化之前修改属性值是以原有的类中的属性值为结果还是反序列化之前修改后的类属性值为结果,这里判断;}
是不是结束是以前面对应的长度决定的,这里也就是s:4:
这个部分。
好啦,以上都是为了这个字符逃逸做铺垫,下面就开始正式讲解PHP反序列化之字符逃逸啦~
标签:字符,123,PHP,--,ss,逃逸,序列化,id From: https://www.cnblogs.com/o-O-oO/p/18340365