php反序列化和字符串逃逸

php反序列化魔术方法

    __construct(),类的构造函数  new的时候触发
    
    __destruct(),类的析构函数  销毁对象的或者serialize时候触发
    
    __call(),在对象中调用一个不可访问方法时调用
    
    __callStatic(),用静态方式中调用一个不可访问方法时调用
    
    __get(),获得一个类的成员变量时调用  当访问一个对象不存在的变量时就会被触发
    
    __set(),设置一个类的成员变量时调用  当给一个对象不存在的变量赋值时就会被触发
    
    __isset(),当对不可访问属性调用isset()empty()时调用
    
    __unset(),当对不可访问属性调用unset()时被调用 当尝试使用unset() 销毁函数去销毁一个不可访问的成员属性时会触发,不可访问(包括私有成员属性,不存在的成员属性)
    
    __sleep(),执行serialize()时,先会调用这个函数 当对象被serialize 序列化时触发调用
    
    __wakeup(),执行unserialize()时,先会调用这个函数 当进行unserialize 反序列化对象时
    
    __toString(),类被当成字符串时的回应方法
    
    __invoke(),调用函数的方式调用一个对象时的回应方法
    
    __set_state(),调用var_export()导出类时,此静态方法会被调用
    
    __clone(),当对象复制完成时调用
    
    __autoload(),尝试加载未定义的类
    
    __debugInfo(),打印所需调试信息
    

字符串逃逸

序列化后的字符串在进行反序列化操作时,会以{}两个花括号进行分界线,花括号以外的内容不会被反序列化。
字符逃逸的主要原理就是闭合,和sql注入类似,只不过它判断的是字符串的长度。输入恰好的字符串长度,让无用的部分字符逃逸或吞掉,从而达到我们想要的目的。

<?php
class people{
    public $name = 'aaa';
    public $sex = 'boy';
 }
$a = new people();
print_r(serialize($a));
$str='O:6:"people":2:{s:4:"name";s:3:"aaa";s:3:"sex";s:3:"boy";}123';
var_dump(unserialize($str));
?>

PHP不会报错,并且也不会输出123.说明{}是字符串反序列化时的分界符。当然,在进行反序列化时,是从左到右读取。读取多少取决于s后面的字符长度。

字符增多逃逸

<?php
class A{
	public $name = 'aaaaaaaaaaaaaaaaaaaaaaaaaa";s:6:"passwd";s:3:"123";}';
	public $passwd = '1234';
}
$ss = new A();
$str = serialize($ss);
//echo $str;
function filter($str){
    return str_replace('aa','bbbb',$str);
}
$tt = filter($str);
echo $tt;
$qq = unserialize($tt);
var_dump($qq);
?>

这段代码主要目的就是间接修改序列化对象里的passwd的值。

“;s:6:“passwd”;s:3:“123”;} 长度26
这里的”;是用来闭合前面的.将该字符串添加到name
这个字符串一共有26字符。我们想要让这段字符串进行反序列化,而;}正好将前面闭合,从而将字符串";s:6:“passwd”;s:3:“123”;}逃逸出去。
然后进行构造:我们输入13个aa就会转换为13个bbbb,多出26个字符,成功将";s:1:“b”;s:3:“104”;}逃逸。

字符减少逃逸

<?php
class A{
	public $name = 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb';
	public $passwd = '1234";s:6:"passwd";s:3:"123';
}
$ss = new A();
$str = serialize($ss);
//echo $str;
function filter($str){
    return str_replace('bb','a',$str);
}
$tt = filter($str);
echo $tt;
$qq = unserialize($tt);
var_dump($qq);
?>

同样道理,我们要将s:6:“passwd”;s:3:“123成功反序列化,那么就要把”;s:6:“passwd”;s:27:"1234 这25个字符吃掉
在name输入25个bb就可以达到效果

原序列化值:

 O:1:"A":2:{s:4:"name";s:50:"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";s:6:"passwd";s:27:"1234";s:6:"passwd";s:3:"123";}

字符串逃逸后

O:1:"A":2:{s:4:"name";s:50:"aaaaaaaaaaaaaaaaaaaaaaaaa";s:6:"passwd";s:27:"1234";s:6:"passwd";s:3:"123";}
这里相当于变量name的值变为aaaaaaaaaaaaaaaaaaaaaaaaa";s:6:"passwd";s:27:"1234 其长度刚好为50后续;s:6:"passwd";s:3:"123刚好和最后形成闭合覆盖了passwd的值成功逃逸
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

XXX_WXY

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值