零基础在实践中学习网络安全-皮卡丘靶场(第十三期-php反序列化)

发布于:2025-06-09 ⋅ 阅读:(16) ⋅ 点赞:(0)

由题目我们可知这个模块需要一定的php基础,但是没有基础的朋友也别担心,我会详细分析与解释的,希望耐心看完

介绍



在理解这个漏洞前,你需要先搞清楚php中serialize(),unserialize()这两个函数。

            序列化serialize()

            序列化说通俗点就是把一个对象变成可以传输的字符串,比如下面是一个对象:



    class S{

        public $test="pikachu";

    }

    $s=new S(); //创建一个对象

    serialize($s); //把这个对象进行序列化

    序列化后得到的结果是这个样子的:O:1:"S":1:{s:4:"test";s:7:"pikachu";}

        O:代表object

        1:代表对象名字长度为一个字符

        S:对象的名称

        1:代表对象里面有一个变量

        s:数据类型

        4:变量名称的长度

        test:变量名称

        s:数据类型

        7:变量值的长度

        pikachu:变量值



            反序列化unserialize()



就是把被序列化的字符串还原为对象,然后在接下来的代码中继续使用。



    $u=unserialize("O:1:"S":1:{s:4:"test";s:7:"pikachu";}");

    echo $u->test; //得到的结果为pikachu





序列化和反序列化本身没有问题,但是如果反序列化的内容是用户可以控制的,且后台不正当的使用了PHP中的魔法函数,就会导致安全问题



        常见的几个魔法函数:

        __construct()当一个对象创建时被调用

        __destruct()当一个对象销毁时被调用

        __toString()当一个对象被当作一个字符串使用

        __sleep() 在对象在被序列化之前运行

        __wakeup将在序列化之后立即被调用

        漏洞举例:

        class S{

            var $test = "pikachu";

            function __destruct(){

                echo $this->test;

            }

        }

        $s = $_GET['test'];

        @$unser = unserialize($a);

        payload:O:1:"S":1:{s:4:"test";s:29:"<script>alert('xss')</script>";}



个人评价:在代码审计或者逆向工程方面有很大帮助,但是需要很多的开发语言基础,因为这个只是php语言的,还有其他语言

适用场景:做代码审计,逆向工程,CTF

实际反馈:如果是打CTF的话,有助于拓展思路,加快解题速度

原理

PHP 反序列化漏洞本质上是由于对用户输入的序列化数据未进行严格验证,导致攻击者可以构造恶意的序列化数据,利用程序中的魔术方法或不安全的类定义来执行恶意操作。

介绍里面说到的内容可能有些麻烦,但是至少我们要了解本模块的知识点,来帮助我们完成靶场。

首先,既然有反序列化,那么一定有序列化的php,我们先了解这个知识

序列化:就像把一个拼好的乐高积木拆开,从而方便装进盒子里存起来

反序列化:就是把盒子里的积木再重新拼成原来的玩具。

由此我们可以知道,php反序列化模块中我们的目标就是把分散开的内容拼接组合好

我们来分析一个实例

<?php

class User {

    public $username;

    public $password;



    public function __construct($username, $password) {

        $this->username = $username;

        $this->password = $password;

    }



    public function __toString() {

        return "User: " . $this->username . ", Password: " . $this->password;

    }

}



if (isset($_GET['data'])) {

    $data = unserialize($_GET['data']);

    echo $data;

}

?>
1. 代码功能

定义了一个

User类,包含username和password两个属性。

__toString()魔术方法用于返回用户信息的字符串格式。

如果$_GET['data']存在,则对$_GET['data']的值进行反序列化,并将其输出。





2. 反序列化漏洞原理

PHP的unserialize()函数会根据输入的序列化字符串创建相应的对象或数组。

如果输入的序列化字符串被攻击者控制,攻击者可以通过构造特定的序列化字符串来触发对象的魔术方法(如__toString()、__destruct()等)。

在这个例子中,攻击者可以通过构造一个包含User对象的序列化字符串,触发__toString()方法。





3. 构造攻击载荷

假设攻击者的目标是通过__toString()方法输出一些恶意信息,比如XSS攻击代码。

攻击者可以构造以下序列化字符串:

O:4:"User":2:{s:8:"username";s:4:"test";s:8:"password";s:18:"<script>alert(1)</script>";}



解释:O:4:"User":2:{}:表示这是一个User对象,对象中有两个属性。

s:8:"username";s:4:"test";:表示username属性的值是test。

s:8:"password";s:18:"<script>alert(1)</script>";:表示password属性的值是<script>alert(1)</script>。





4. 攻击过程

攻击者将构造好的序列化字符串通过URL参数传递给脚本:

http://example.com/vulnerable.php?data=O:4:"User":2:{s:8:"username";s:4:"test";s:8:"password";s:18:"<script>alert(1)</script>";}

当脚本执行时:

unserialize()函数将序列化字符串解析为User对象。echo $data会触发User对象的__toString()方法。

__toString()方法返回

User: test, Password: <script>alert(1)</script>,并将其输出到页面。浏览器会执行

<script>alert(1)</script>,弹出一个警告框。

实践

在上面的介绍中,我们就获取了一个标准的攻击内容

O:1:"S":1:{s:4:"test";s:29:"<script>alert('xss')</script>";}

输进去

完成

可能很多朋友会觉得云里雾里,不明白,因为这个模块需要一定的php基础,如果不了解的话,哪怕了解的序列化和反序列化也很难理解,但是只要努力学习,终究会理解的