什么是序列化和反序列化.先理解一下类和对象的概念

类:类是具有相同属性和操作的一组对象的集合。每个类的定义都以关键字 class 开头,后面跟着类名,后面跟着一对花括号,里面包含有类的属性与方法的定义。例如:

class Test{
    public $a;
    public function b{
      do sth...
    }
}

上面的代码定义了一个类Test,里面有一个属性(变量)a,一个方法b(函数).
对象:object,把封装的类进行实例化后就是对象

class Test{};   //定义一个类
$test = new Test();  //类的实例化就是对象

序列化和反序列化:

serialize:将一个对象序列化成一个字符串变量.
unserialize:将字符串重建成一个对象.

class Test{
    public $a="Hello world";
    public $b=20;
}
$obj = new Test();
$obj->a="welcome";
$ser = serialize($obj);   //序列化对象obj赋值给ser
echo $ser;
$unser = unserialize($ser); //将ser反序列化成对象unser
echo $unser->a;

输出后结果如下:

O:4:"Test":2:{s:1:"a";s:7:"welcome";s:1:"b";i:20;}
welcome

简单来说序列化就是把一个类中所有变量的值以一定的格式转化成字符串,反序列化就是把这一串特定格式的字符串重建成为一个对象,并继承类中的所有方法.
序列化的格式为:

O:4:"Test":2:{s:1:"a";s:5:"Hello";s:1:"b";i:20;}
类型:长度:"名字":类中变量的个数:{类型:长度:"名字";类型:长度:"值";......}

类型字母详解:

a - array  
b - boolean  
d - double  
i - integer
o - common object
r - reference
s - string
C - custom object
O - class
N - null
R - pointer reference
U - unicode string

web中反序列化漏洞中主要涉及的是php的魔术方法(magic function),由双下划线开头的函数如__construct等函数在某些情况下会自动调用:

<?php 
    class Test{
        public $a="hello world";
        public function __construct(){
            $this->a="welcome";
        }
    }
    $obj = new Test();
    $ser = serialize($obj);   //序列化对象obj赋值给ser
    $unser = unserialize($ser); //将ser反序列化成对象unser
    echo $unser->a;
?>

这段代码输出的结果是"welcome"而不是hello world,原因是在反序列化的时候自动调用了__construct函数将a的值改变为了"welcome";

常用的魔术方法及触发条件:

__wakeup() //使用unserialize时触发
__sleep() //使用serialize时触发
__destruct() //对象被销毁时触发
__call() //在对象上下文中调用不可访问的方法时触发
__callStatic() //在静态上下文中调用不可访问的方法时触发
__get() //用于从不可访问的属性读取数据
__set() //用于将数据写入不可访问的属性
__isset() //在不可访问的属性上调用isset()或empty()触发
__unset() //在不可访问的属性上使用unset()时触发
__toString() //把类当作字符串使用时触发,返回值需要为字符串
__invoke() //当脚本尝试将对象调用为函数时触发

反序列化的利用:

利用条件:变量可控并且进行反序列化.看下面一段代码

<?php 
    class Test{
        public $a="hello";
        public function c(){
            system("type $this->a.txt");
        }
    }
    $ser = $_GET['id'];
    $obj = unserialize($ser);
    $obj->c();
?>

创建两个文本hello.txt 和flag.txt 然后访问网址:
http://localhost/test.php?id=O:4:%22Test%22:1:{s:1:%22a%22;s:5:%22hello%22;}
1.jpg
修改一下传入的参数:
http://localhost/test.php?id=O:4:%22Test%22:1:{s:1:%22a%22;s:4:%22flag%22;}
2.jpg
可见,反序列化漏洞就是通过控制变量而执行预计之外的代码.主要利用还是要看代码的逻辑,以及绕过的方法.

有写的不对的请大佬指出..