反序列化 漏洞

0x00 序列化与反序列化

语言结构

  • 序列化的定义是,将对象的状态信息 转换为可以存储或传输的形式 (字符串)的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。

  • 简单的说,序列化就是把—个对象变成可以传输的字符串,可以以特定的格式在进程之间跨平台、安全的进行通信。

序列化的用途

  • 方便对象在网络中的传输与存储

序列化与反序列的过程

  • 序列化:将对象转换为流,利于储存和传输的格式

  • 反序列化:将流转换为对象

序列化的过程

  • 首先创建一个类,类名是 Stu,该类有 4 个属性。用这个 Stu 类 new 一个$stu1 对象,使用 serialize() ,将 $stu1 这个对象序列化成一个字符串,这样的字符串容易传输和存储。

  • 测试代码:

// class.php

<?php
class Stu{
  public $name;
  public $sex;
  public $age;
  Public $score;
}

$stu1 = new Stu();
$stu1->name = "ichunqiu";
$stu1->sex = true;
$stu1->age = 18;
$stu1->score = 89.9;
echo serialize($stu1);

?>

序列化的结果

  • O:3:"Stu":4 // O 代表 Object 对象;3 代表 对象名有三个字符;4 代表 对象中有 4 个属性

  • {s:4:"name"; // s 代表 属性数据类型,s 代表 string,i 代表 int;4 代表 属性 长度;name 是 属性名

  • s:8:"ichunqiu"; // s 代表 属性数据类型,s 代表 string,i 代表 int;8 代表 属性 长度;ichunqiu 是 属性值

  • b:1; // b 代表 bool

  • 后面的属性名和属性值依次类推

反序列化的过程

  • 测试代码:
<?php
include "class.php";
$stu =
<<<STR
O:3:"Stu":4:{s:4:"name";s:8:"ichunqiu";s:3:"sex";b:1;s:3:"age";i:18;s:5:"score";d:89.900000000000006;}
STR;
$stu1 = unserialize($stu1);
var_dump($stu1);
?>

反序列化的结果

0x01 反序列化漏洞 概述

PHP 反序列化漏洞 概述

  • 概念:PHP 反序列化漏洞也叫 PHP 对象注入

  • 危害:这种类型的漏洞虽然有些难以利用,但一旦利用成功就会造成非常危险 的后果

  • 形成原因:程序没有对用户输入的反序列化字符串进行检测 ,导致反序列化过程可以被恶意控制,进而造成代码执行、getshell 等一系列不可控的后果。反序列化漏洞并不是 PHP 特有,也存在于 Java、 Python 等语言之中,但其原理基本相通

常见的魔法函数介绍

  • 在学习过序列化与反序列化的过程之后,我们知道,序列化本身并不存在任何漏洞 ,但是搭配上 PHP 的魔法函数 ,整个程序的执行流程就将变得可控
  1. __construct():当一个对象创建 时被调用(相当于 c++ 的构造函数)。

  2. __destruct(): 当一个对象销毁 时被调用(相当于 c++ 的析构函数)。

  3. __sleep(): 当在对象被序列化之前 被调用。

  4. __wakeup(): 当在 unserialize()函数执行反序列化时 调用。

  5. __toString(): 当一个对象被当作一个字符串 时使用。

测试代码

<?php
class Test{
        public $str='ichunqiu';
        function __construct()
        {
                echo '_construct() is execute!!!<br>';
        }
        function __destruct()
        {
                echo '<br>_destruct() is execute!!!<br>';
                @system($this->str);
        }
        function __wakeup()
        {
                echo '_wakeup() is execute!!!<br>';
                $fp = fopen("shell.php","a+");
                fwrite($fp,$this->str);
                fclose($fp);
        }
        function __sleep()
        {
                echo '_sleep() is execute!!!<br>';
                return array('str');
        }
        function __tostring()
        {
                echo 'tostring() is execute!!!<br>';
                return "testvalue";
        }
}

$test = new Test();
echo "hello!!!".$test.'<br>'; 
echo serialize($test).'<br>';
var_dump(unserialize($_GET['code']));
?>

测试代码执行结果

0x02 反序列化漏洞 原理

  • 程序没有对用户输入的反序列化字符串进行检测,导致反序列化过程可以被恶意控制,进而造成代码执行、getshell 等一系列不可控的后果

0x03 反序列化漏洞 利用

绕过 __wakeup()

绕过原理

  • 当序列化后的字符串的属性个数字段大与真实属性个数 时,会跳过__wekeup()函数 执行

绕过示例

  • 正常属性值 1,__wekeup()函数 正常执行

  • 比之前属性1大的2,__wekeup()函数 被成功绕过,whoami命令成功执行

0x04 反序列化漏洞 防御

  • 不要反序列化不可信的数据

  • 给反序列数据加密签名,并确保解密在反序列之前

  • 给反序列化接口添加认证授权

posted @ 2021-11-21 10:45  FreeK0x00  阅读(238)  评论(0编辑  收藏  举报