常见的Serialize与Unserialize之「序列化与反序列化」
in Code-Audit with 0 comment

常见的Serialize与Unserialize之「序列化与反序列化」

in Code-Audit with 0 comment

什么是序列化及反序列化

序列化 :将数据结构或对象转换成二进制串的过程
反序列化:将在序列化过程中所生成的二进制串转换成数据结构或者对象的过程

单纯丛概念上来说,序列化和反序列化属于通讯协议的一部分。在OSI七层协议模型中展现层(Presentation Layer)的主要功能是把应用层的对象转换成一段连续的二进制串,或者反过来,把二进制串转换成应用层的对象--这两个功能就是序列化和反序列化。

序列化和反序列化需要完成什么

关键字:在应用程序中 “对象持久化”“对象传输”
概念重构:在应用程序中"将对象转换成为字节序列的过程称为对象的序列化,反之将字节序列恢复为对象的过程称之为反序列户"

对象持久化: 类实例化一个对象后,操作系统为该对象分配一块内存空间。将对象的字节序列永久地存储在硬盘上,在需要的时候还原,这是序列化的一个用途。
对象传输:在网络上传输的信息最终形式是二进制串,由于没有一种数据结构能直接表示对象,所以在数据传输时需要将对象转换为二进制串,以便进行网络传输。

php serialize()和unserialize()

由于php很好地支持范数据类型,在php中数组和对象可以相互转换。数组和对象均支持序列化和反序列化。

所有php里面的值都可以使用函数serialize()来返回一个包含字节流的字符串来表示。unserialize()函数能够重新把字符串变回php原来的值。 序列化一个对象将会保存对象的所有变量,但是不会保存对象的方法,只会保存类的名字。

php对象的序列化和反序列化

<?php
class dr0op{
    private $name ="dr0op";
    private $age = 100;
    private $team = "K4l0nG";
    public function print_name(){
        echo $this->name;
    }
}
$dr0op = new dr0op();
$sdr0op = serialize($dr0op); //使用serialize函数序列化$dr0op对象
echo $sdr0op;
?>

serialize序列化之后生成的字符串是不可读的
O:5:"dr0op":3:{s:11:"dr0opname";s:5:"dr0op";s:10:"dr0opage";i:100;s:11:"dr0opteam";s:6:"K4l0nG";}

serialize序列化和json序列化区别

json序列化和反序列化丢失了类中的私有成员变量,而serialize序列化和反序列化只要是类的变量都可以,但是类的成员方法都无法进行序列化和反序列化。
json序列化只对UFT-8的数据有效,其他编码可能不能很好工作。serialize序列化对其他编码支持良好
json序列化之后的文本可读性强,而serialize序列化之后的文本一般不可读。

对如上代码进行json序列化

<?php
class dr0op{
    public $name ="dr0op";
    public $age = 100;
    public $team = "K4l0nG";
    public function print_name(){
       echo $this->name;
    }
}
$dr0op = new dr0op();
$sdr0op = json_encode($dr0op); //对$dr0op对象进行json序列化
var_dump($sdr0op);

?>

序列化之后生成json字符串:
"{"name":"dr0op","age":100,"team":"K4l0nG"}"

反序列化

对如上生成的序列化字符串进行反序列化操作。在对象进行反序列化操作时,需要找到对象所在类的声明,如果没有找到,则会变成一个__PHP_Incomplete_Class类的非完全对象。

<?php
class dr0op{
}
$sdr0op='O:5:"dr0op":3:{s:4:"name";s:5:"dr0op";s:3:"age";i:100;s:4:"team";s:6:"K4l0nG";}';
$udr0op = unserialize($sdr0op);
echo $udr0op->name;    //dr0op
$jedr0op ='{"name":"dr0op","age":100,"team":"K4l0nG"}';
$jddr0op = json_decode($jedr0op);
echo $jddr0op->name;  //dr0op
?>

java中Serializable接口

java中对象序列化机制(object serialization)是Java语言内建的一种对象序列化机制。只需要implement
java.io.Serializeable接口,并使用java内建的"ObjectOutputStream/ObjectInputStream"类即可完成对象读写。

import java.io.Serializable; 
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
   class Student implements Serializable{
      private String name;
      public Student(String name){
         this.name = name;
      }
      public String getName(){
         return name;
      }
   }

   class StudentSerializer{
      public static void main(String[] args) throws Exception{
         // 实例化一个student对象
         Student st = new Student("jason");

        // 序列化对象到文件
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("jason.se"));
        oos.writeObject(st);
        oos.close();

        //从文件中反序列化对象
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("jason.se"));
        Student jason = (Student) ois.readObject();
        ois.close();

       // 比对序列化和反序列化前后对象
       assert "jason".equals(jason.getName());
      }
   }

python中的pickling和unpickling

在Python中,一切皆对象。

Python提供两个模块来实现序列化:cPickle和pickle。这两个模块功能是一样的,区别在于cPickle是C语言写的,速度快,pickle是纯Python写的,速度慢,跟cStringIO和StringIO一个道理。用的时候,先尝试导入cPickle,如果失败,再导入pickle:

# 序列化
with open('abc.pkl', 'wb') as f: 
dic = {'age': 23, 'job': 'student'} 
pickle.dump(dic, f) # 
#反序列化
with open('abc.pkl', 'rb') as f: 
aa = pickle.load(f)
print(aa) 
print(type(aa)) # <class 'dict'>

我们知道JSON表示的对象是标准的javascript语言对象
Python内置的json模块提供了非常完善的Python对象到JSON格式的转换

JSON序列化

>>> import json
>>> d = dict(name='Bob', age=20, score=88)
>>> json.dumps(d)
'{"age": 20, "score": 88, "name": "Bob"}'

JSON反序列化

>>> json_str = '{"age": 20, "score": 88, "name": "Bob"}'
>>> json.loads(json_str)
{u'age': 20, u'score': 88, u'name': u'Bob'}

javascript对象序列化与反序列化

js中的对象传递很简单

json序列化

使用toJSONString

var last=obj.toJSONString(); //将JSON对象转化为JSON字符

使用stringify

var last=JSON.stringify(obj); //将JSON对象转化为JSON字符

反序列化

使用evel

var obj=eval("("+data+")");

使用parseJSON

var obj = data.parseJSON(); //由JSON字符串转换为JSON对象

使用parse

var obj = JSON.parse(data); //由JSON字符串转换为JSON对象

总结

序列化操作是便于对象传输和对象持久化的一种解决方式。在反序列化过程中产生的漏洞其本质就是反序列化机制打破了数据和对象的边界,导致攻击者注入的恶意序列化数据在反序列化过程中被还原成对象,控制了对象就可以在目标系统上执行任意代码。

参考链接

https://blog.csdn.net/c0c0cf/article/details/52551183
https://blog.csdn.net/cpf2016/article/details/50481508
https://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/00138683221577998e407bb309542d9b6a68d9276bc3dbe000
https://www.cnblogs.com/sun-haiyu/p/7087088.html
https://blog.csdn.net/jason_279/article/details/52947093

Responses