zoukankan      html  css  js  c++  java
  • PHP序列化入门

    通过序列化与反序列化我们可以很方便的在PHP中进行对象的传递。本质上反序列化是没有危害的。但是如果用户对数据可控那就可以利用反序列化构造payload攻击。

    php序列化的作用:

    上面的话翻译的直白一点就是方便存储和运输以及传递,举个例子就是:如果想把一个数组或者是对象存储到文件或数据库中,怎么办。不能像字符串那样的存储吧。所以在存储数组或对象之前先对数据进行serialize,在取回内容时再unserialize

    也许有人回想,json不也一样吗,我也这样想过,所以去找了一下json和序列化的查别以及优缺点

    这里我只把优缺点结果贴出来,详细对比过程可以去这个帖子里看:https://blog.51cto.com/zhweizhi/1952116

      json serialize
    优点
    • 变量序列化后依然可读

    • 可以给其他系统使用,因为JSON格式是标准的

    • 允许非UTF-8的变量

    • 支持除了stdClass 示例外的其他实例

    缺点
    • 只对UFT-8的数据有效,其他编码可能不能很好工作

    • 只对stdClass类的示例有效

    • 编码后的文本对人来说是不可读的

    • 无法被其他语言的系统引用

    同时在那篇文章最后可以看到:

    “我们发现,json序列化和反序列化丢失了类中的私有成员变量,而serialize序列化和反序列化只要是类的变量都可以,但是类的成员方法都无法进行序列化和反序列化。

    在一般情况,还是使用json比较好,因为json是跨平台的通用格式,除了json,用xml也比较好。那在什么时候使用serialize方式呢?

    在对一个类进行serialize反序列化的时候会默认调用魔术方法__wakeUp(),这样就使得对象能够重新建立起序列化时未能保留的各种状态。例如:数据库连接等。那就是另外一个问题了,这里不做深究了。”

    再重新说回serialize序列化

    serialize()    //将一个对象转化成一个字符串

    unserialize()   //将一个字符串转化成一个对象

    <?PHP
    class test
        {
            private $flag = "flag{233}";
            public $a = "aaa";
            public $b = 1234;
            static $c = "bbb"; }
    $test = new test; $data = serialize($test); echo $data; ?> //O:4:"test":3:{s:10:"testflag";s:9:"flag{233}";s:1:"a";s:3:"aaa";s:1:"b";i:1234;}

    解释一下怎么看serialize的结果

    O:4:"test"表示object名字有四个字符串

    :3表示对象属性有点两个(flag,a)

    {}里的是属性的值

    •   s:10:"testflag"表示string类型,长度为10,值为"testflag"
    •   i:1234表示int类型,值为1234

    这里有个细节要注意,flag只有4,testflag也只有8,但是这里显示的长度却是10。这是因为它是private属性,翻阅文档就可以看到说明,它会在两侧加入空字节。所以在传入序列化字符串进行反序列化时需要注意补齐两个空字节。

    再扯一下public、protected、private下序列化对象的区别

    • public变量
      •   直接变量名反序列化出来
    • protected变量
      •     x00 + * + x00 + 变量名
    • private变量
      •     x00 + 类名 + x00 + 变量名

    比较重要的两个方法:

    __sleep()
       serialize() 函数会检查类中是否存在一个魔术方法 __sleep()。如果存在,该方法会先被调用,然后才执行序列化操作。此功能可以用于清理对象,并返回一个包含对象中所有应被序列化的变量名称的数组。如果该方法未返回任何内容,则 NULL 被序列化,并产生一个 E_NOTICE 级别的错误。
      对象被序列化之前触发,返回需要被序列化存储的成员属性,删除不必要的属性。


    __wakeup()
      unserialize() 会检查是否存在一个 __wakeup() 方法。如果存在,则会先调用 __wakeup 方法,预先准备对象需要的资源。
      预先准备对象资源,返回void,常用于反序列化操作中重新建立数据库连接或执行其他初始化操作。

    绕过__wakeup()

    CVE-2016-7124漏洞,当序列化字符串中表示对象属性个数的值大于真实的属性个数时会跳过__wakeup的执行正常序列化对象后是这样的:↓

    构造序列化对象:O:5:"SoFun":1:{S:7:"0*0file";s:8:"flag.php";}
    绕过__wakeup:O:5:"SoFun":2:{S:7:"0*0file";s:8:"flag.php";}

  • 相关阅读:
    mac登录界面的背景壁纸图片位置
    【转载】MAC系统修改帐号短名和个人文件夹名称
    ios 6.x系统UITextView 设置为密码输入无效的问题
    一个简单的果冻弹动动画
    ios中的自动释放池
    ios 静态库联合调试
    【转】IOS制作静态库
    objective-c中为什么不能实现多重继承及如何变通实现
    回调中释放自己会不会导致崩溃?
    【转载】Objective-C runtime 消息机制
  • 原文地址:https://www.cnblogs.com/This-is-Y/p/12469046.html
Copyright © 2011-2022 走看看