1. PHP变量覆盖漏洞实战解析第一次看到这个题目的时候我差点笑出声来。PHP是世界上最好的语言这个梗在程序员圈子里流传已久但没想到在CTF赛场上还能遇到这样的彩蛋。不过玩笑归玩笑这道题其实暗藏玄机考察的是PHP变量覆盖这个经典漏洞。先来看题目给出的源码。关键点在于parse_str()和extract()这两个函数的使用。parse_str()函数会把查询字符串解析到变量中而extract()则能从关联数组中提取变量。这两个函数如果使用不当就会造成变量覆盖漏洞。我遇到过不少新手会问什么是变量覆盖简单来说就是攻击者可以通过外部输入覆盖掉程序内部已经定义好的变量值。比如题目中原本设置了$key1和$key2的初始值为0但通过精心构造的输入我们可以把它们改成任意值。具体到这道题我们需要让$flag1和$flag2都等于8gen1。但直接传flag1和flag2参数会被检测到并拒绝。这时候就要用到变量覆盖的技巧了。我的做法是通过GET传参?_POST[flag1]8gen1_POST[flag2]8gen1。这样就能绕过第一层检测。接下来要处理的是504_SYS.COM这个参数。这里有个小技巧用方括号[]来绕过点号的限制。因为PHP在处理变量名时会把[转换成下划线_但后面的字符会保留下来。所以传504[SYS.COM就能成功绕过过滤。最后执行命令的部分由于很多特殊字符都被过滤了直接读取flag.php比较困难。但注意到源码中已经包含了flag.php所以直接输出$flag变量就能拿到flag。最终的payload是这样的POST /index.php?_POST[flag1]8gen1_POST[flag2]8gen1 HTTP/1.1 ... 504[SYS.COM1sysecho $flag;2. 反序列化漏洞与POP链构造反序列化漏洞在CTF中出现的频率相当高这道题就是一个典型的例子。题目给出了两个类example和process。我们的目标是通过反序列化构造一个POP链Property-Oriented Programming chain最终实现任意代码执行。先分析一下代码逻辑。example类有一个__destruct魔术方法这个方法会调用funnnn函数而funnnn函数又会调用$handle对象的close方法。process类中的close方法直接eval执行了$this-pid的内容。要构造POP链我们需要创建一个example对象将其handle属性设置为process对象设置process对象的pid属性为要执行的代码这里有个小技巧通过__construct构造函数来自动完成这些设置。我写的构造代码如下class example { public $handle; function __construct(){ $this-handlenew process(); } } class process{ public $pid; function __construct(){ $this-pideval($_POST[123]);; } } $testnew example(); echo serialize($test);生成的序列化字符串是这样的O:7:example:1:{s:6:handle;O:7:process:1:{s:3:pid;s:21:eval($_POST[123]);;}}把这个字符串作为data参数传给页面就能成功植入一句话木马。之后用蚁剑等工具连接就能获取服务器权限。在实际渗透测试中这种反序列化漏洞往往能直接拿到系统权限危害性非常大。3. 字符串比较绕过的黑魔法BlackMagic这道题的名字起得很贴切确实用到了不少黑魔法。题目提示flag就在页面里但直接访问什么都看不到。查看源代码后发现关键逻辑使用extract($_REQUEST)提取变量对strFlag进行trim处理得到strContent比较strTmp和strContent是否相等这里的突破口在于trim函数。trim会去除字符串两端的空白字符但不会处理中间的。而PHP的松散比较在某些情况下会把包含空白字符的字符串视为相等。经过测试我发现用水平制表符%09可以绕过这个比较。payload如下?strTmp%09xxxxx...xxxxx%09这个技巧在真实环境中也很有用。很多系统会对用户输入进行trim处理但后续比较时可能使用松散比较。了解这些细节差异往往能找到意想不到的突破点。4. 命令执行过滤绕过技巧再来ping一波啊这道题看似简单实则暗藏杀机。表面上是个命令注入漏洞但几乎所有常用命令和字符都被过滤了。包括常见命令ls、cat、tac特殊字符空格、斜杠、点号面对这种情况我尝试了几种绕过方法使用变量拼接;adex;ca\t$IFS$1in$a.php使用反斜杠转义ta\c$IFS$9$a$b.php使用$IFS代替空格其中$IFS是Linux中的内部字段分隔符默认就是空格。通过这种技巧我们成功绕过了空格的限制。读取index.php后发现flag其实就在源代码注释里。这种过滤绕过的技巧在实际渗透中很常见。WAFWeb应用防火墙通常会过滤大量危险字符和命令但通过字符编码、变量替换、命令拼接等方法往往能找到突破口。5. 无字母Shell与死亡代码绕过最后这道找找Shell可以说是集大成者考察的是文件写入和死亡代码die/exit绕过的技巧。题目允许我们通过file_put_contents写入文件但会在内容前加上这被称为死亡代码会阻止后续代码执行。我尝试了两种绕过方法第一种是base64编码?filenamephp://filter/convert.base64-decode/resourcetest.php contentaPD9waHAgc3lzdGVtKCdscyAvJyk/Pg这里有个细节我在内容前加了个字母a因为base64解码时是4字节转3字节。加上这个a就能保证死亡代码被完全解码成乱码。第二种方法是组合使用多个过滤器?filenamephp://filter/string.strip_tags|convert.base64-decode/resources1mple.php content?gt;PD9waHAgc3lzdGVtKCdscycpPz4strip_tags会去除XML标签包括这样死亡代码就被移除了。之后再base64解码就能正常执行我们的代码。这种无字母Shell的技巧在真实环境中非常实用特别是当服务器限制了字符集或过滤了某些函数时。通过编码转换和过滤器组合往往能突破这些限制。