1. 从一道CTF题说起:为什么unseping值得深挖?
大家好,我是老张,在安全圈摸爬滚打十来年,特别喜欢研究那些看起来简单、实则暗藏玄机的漏洞。今天想和大家聊聊攻防世界(CTF)里的一道进阶题——unseping。这道题我印象很深,因为它完美地把PHP反序列化和命令执行绕过这两个“老朋友”结合在了一起,形成了一个非常经典的攻击链。很多刚入门代码审计的朋友,看到反序列化可能知道个大概,但一遇到WAF过滤和命令绕过就有点懵了。这道题正好是一个绝佳的实战演练场。
简单来说,这道题的场景是:给你一个存在漏洞的PHP网页,你需要通过构造特定的输入,最终让服务器执行你的命令,从而找到隐藏的flag。这听起来像是“黑盒测试”,但题目直接把源码给你看了,这就变成了“白盒审计”。你的武器就是代码审计能力、对PHP魔术方法的理解,以及一点点绕过过滤的奇思妙想。我当年带新人时,就喜欢用这道题来检验他们是不是真的把知识点串起来了。接下来,我会把自己拆解这道题的完整思路、踩过的坑,以及几种不同的绕过姿势,毫无保留地分享给你。咱们不搞理论空谈,直接上手干。
2. 庖丁解牛:深度审计题目源码
拿到任何一道代码审计题,第一步永远是静下心来读代码。别急着构造payload,理解程序的每一块“肌肉”和“骨骼”是如何运作的,往往能事半功倍。题目给出的源码不长,但信息量巨大,我们逐行来看。
2.1 核心类结构与魔术方法
整个代码的核心是一个名为 ease 的类。类里面定义了私有属性 $method 和 $args,以及几个关键的魔术方法。所谓魔术方法,就是以双下划线 __ 开头的方法,它们会在特定时机被PHP自动调用,这是理解反序列化漏洞的关键。
首先登场的是 __construct,也就是构造函数。当你用 new ease("ping", array("whoami")) 这样的方式实例化一个对象时,构造函数会自动执行,把传入的参数赋值给对象的属性。这里,$method 被设为 "ping",$args 被设为一个数组 array("whoami")。
接下来是重头戏 __wakeup()。这个方法的名字很形象,“唤醒”。当PHP函数 unserialize() 反序列化一个字符串,试图将其还原成一个对象时,如果这个对象的类中定义了 __wakeup() 方法,那么在反序列化完成、对象生成之前,这个方法会首先被调用。题目中的 __wakeup() 干了件很重要的事:它遍历 $this->args 数组中的每一个值,并调用 waf() 函数进行过滤。这意味着,任何通过反序列化传入的 $args 参数,都要先过一遍WAF的检测。
然后是最关键的 __destruct(),析构函数。当一个对象的所有引用都被删除,或者脚本执行结束时,这个对象会被销毁,此时析构函数会自动执行。在题目中,__destruct() 的逻辑是:检查 $this->method 的值是否在允许的数组(目前只有 "ping")里。如果在,就使用 call_user_func_array 调用对象自身的 ping 方法,并把 $args 作为参数传进去。
最后是真正的执行点 ping($ip) 方法。它直接调用了 exec($ip, $result),并将结果用 var_dump 打印出来。exec()


2000

被折叠的 条评论
为什么被折叠?



