[0CTF 2016]piapiapia

Oyst3r 于 2023-09-03 发布

前言

这道题接触到了很多之前没见过的新知识,解题过程中学到了不少有趣的技巧和思路,特别是文件包含和反序列化相关的利用手段。尽管解题过程中遇到了不少坑,但最终解决还是非常有成就感的。

题目分析

1. 登陆框分析

题目一开始给了一个登陆框,惯例下意识地认为是 SQL 注入,于是尝试手工和 SQLMap 跑了一下,但无论是 F12 抓包,还是 SQLMap 工具测试,发现都没有明显的 SQL 注入痕迹。

为此,我试了御剑和 Disreash 跑目录,但奇怪的是,不同的工具跑出来的结果居然不同。在使用 Disreash 时,因为线程开高了一点导致 IP 被封,之后调整到低线程继续尝试,最终也没跑出什么结果。后来参考了 WP,才发现正确路径在于寻找备份文件。

注意:备份文件为www.zip,御剑可以跑出来,而 Disreash 没能识别到。因此工具的选择也很重要。

2. 源码审计

通过备份文件www.zip拿到整个网站的源码,接下来就是源码审计了。我将代码放到了 Seay 审计工具中进行快速扫描。

源码审计

通过审计,发现了漏洞的源头:profile.php文件包含问题。在代码中,有一个config.php文件,其中有一个flag的变量,但是并没有值。

通过反复分析,发现这个文件主要是用来引导我们往文件包含方向走。真正的关键在于如何将config.php的内容包含进来,并读取其中的flag。最后发现,在update.php文件中,程序存在反序列化漏洞,这个文件通过POST方式接受数据并进行序列化操作。

但这里存在一个特殊点:过滤操作是在反序列化完成后才执行的,这跟通常遇到的序列化前过滤有所不同。

3. 利用反序列化漏洞

观察代码后,联想到了之前做过的类似题目,想到反序列化时可以通过手工构造字符串,利用提前结束符号";}来逃逸。尝试构造了以下 payload:

s:3:"abc";s:5:"photo";s:10:"config.php";}

但是,这样构造存在一个问题:反序列化时config.php被当作nickname的一部分,而不是photo字段内容。解决这个问题需要进一步深入分析过滤函数。

通过继续分析,发现过滤操作其实可以用来制造字符空间。在反序列化后,对字段进行了长度验证,并且通过构造膨胀字符来挤出空间。也就是说,利用字符替换的技巧可以成功将config.php包含到photo字段中。

4. 绕过正则匹配

题目还对nickname字段有长度限制,这里可以抓包修改,直接将nickname[]作为绕过手段。抓包后修改nickname的值为以下 payload:

s:8:"nickname";a:1:{i:0;s:204:"34*where";}s:5:"photo";s:10:"config.php";}

正则替换后,得到:

s:8:"nickname";a:1:{i:0;s:204:"34*hacker";}s:5:"photo";s:10:"config.php";}

由于字符数达到了限制,因此config.php成功被挤进了photo字段,反序列化成功结束。

5. 最终Payload

构造完成的payload如下:

wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}

通过抓包,修改请求参数并重新发送。最终在响应中成功得到了base64编码的flag,解码之后便是题目的flag。

总结

这道题目设计巧妙,尤其是反序列化漏洞的利用点和后续的字符挤出技巧,非常值得学习。整个解题过程虽然有些卡顿,但思路非常清晰。希望以后在做题时,遇到类似情况可以更快反应过来,节省不必要的时间。