![BUUCTF [ZJCTF 2019]NiZhuanSiWei 通关详解:从PHP伪协议到反序列化的三层渗透](http://pic.xiahunao.cn/yaotu/BUUCTF [ZJCTF 2019]NiZhuanSiWei 通关详解:从PHP伪协议到反序列化的三层渗透)
1. 题目初探与源码分析第一次看到这道题的时候我盯着屏幕上的PHP源码看了足足五分钟。题目给出了一个简单的PHP文件要求我们通过三个参数来获取flag。这种层层递进的题目设计在CTF中很常见但每一步都需要仔细思考。源码的核心逻辑是这样的首先检查text参数要求读取文件内容为welcome to the zjctf然后检查file参数会过滤flag关键字最后password参数需要进行反序列化操作。这种设计就像是三道门每道门都有不同的锁我们需要找到对应的钥匙才能通过。我特别喜欢这种分步骤的题目因为它能让我们清晰地看到每个安全漏洞是如何被利用的。下面我就带大家一步步破解这三道防线。2. 第一关data伪协议的妙用2.1 理解第一层防御第一关要求text参数读取的文件内容必须是welcome to the zjctf。看起来很简单但问题在于我们根本没有这样一个文件这时候就需要用到PHP的data伪协议了。data协议允许我们直接在URL中嵌入数据就像是在本地创建了一个临时文件。它的基本格式是data://text/plain,内容2.2 构造payload我尝试了最简单的payload?textdata://text/plain,welcome to the zjctf但有时候直接传递明文可能会遇到编码问题所以更稳妥的做法是使用base64编码。先用在线工具把welcome to the zjctf转成base64得到d2VsY29tZSB0byB0aGUgempjdGY然后构造?textdata://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY这样就能顺利通过第一关了。记住这个小技巧data协议在很多CTF题目中都能派上用场。3. 第二关绕过文件读取限制3.1 分析源码限制第二关的代码会检查file参数中是否包含flag字符串如果包含就直接退出。这明显是为了防止我们直接读取flag.php文件。但是代码中给出了一个重要提示useless.php。3.2 使用php://filter协议这时候php://filter协议就派上用场了。这个协议可以用来对文件内容进行各种处理比如base64编码。我们可以用它来读取useless.php的源码filephp://filter/readconvert.base64-encode/resourceuseless.php服务器会返回base64编码后的文件内容我们解码后就能看到useless.php的源代码了。这个技巧特别实用因为它可以绕过很多文件读取的限制。3.3 分析useless.php解码后得到的源码中有一个Flag类这个类会在反序列化时读取指定的文件内容。这给了我们重要提示flag可能就在flag.php中而我们需要通过反序列化来获取它。4. 第三关反序列化攻击4.1 理解反序列化漏洞这是最有趣的一关。useless.php中的Flag类在反序列化时会读取file属性指定的文件。这就是典型的反序列化漏洞利用场景。我们需要构造一个序列化字符串当它被反序列化时会读取flag.php的内容。具体来说我们需要创建一个Flag对象其file属性值为flag.php。4.2 构造payload我写了个简单的PHP脚本来生成序列化字符串?php class Flag { public $file flag.php; } echo serialize(new Flag()); ?运行后会得到O:4:Flag:1:{s:4:file;s:8:flag.php;}4.3 最终攻击链现在我们可以把所有部分组合起来?textdata://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGYfileuseless.phppasswordO:4:Flag:1:{s:4:file;s:8:flag.php;}这样就能成功触发反序列化漏洞读取flag.php的内容。记得查看网页源代码flag通常会在注释或者某个隐藏的div中。5. 防御措施与思考做完这道题后我思考了一下如何防御这类攻击。首先对于文件包含应该限制可包含的文件路径其次反序列化操作要特别小心最好避免反序列化用户输入最后敏感文件如flag.php应该设置适当的权限。这道题很好地展示了如何将多个漏洞串联起来进行攻击。在实际开发中我们需要注意每一个环节的安全因为攻击者往往会寻找最薄弱的环节入手。