攻防世界 warmup
第一次打开warmup这道题时,攻防我差点以为平台出bug了。世界页面就一张静态图,攻防一个输入框,世界连个提示都没有。攻防直到我习惯性地按F12,世界才发现端倪——源码里藏着一行注释,攻防写着source.php。世界那一刻我笑了,攻防这就像有人把钥匙放在门口地垫下,世界还特意贴了张便条告诉你位置。攻防
访问source.php,世界代码直接摊开在眼前。攻防PHP代码不到二十行,世界核心就一个include $_GET['file']。攻防典型的文件包含漏洞,但真正有趣的地方在于那个if判断:它检查参数里是否含有source.php或者hint.php,如果包含就直接输出“nononono”。我第一次尝试?file=source.php,果然被拦了。可当我改成?file=source.php%3f,居然绕过去了——因为URL解码后%3f变成问号,而代码用的是strpos做子串匹配,问号让整个字符串变成了source.php?,不再包含原始关键字。
这种绕过方式让我愣了一下。不是因为它多高深,恰恰相反,它简单到让人怀疑自己是不是想复杂了。真正的漏洞利用往往就是这样——你绞尽脑汁构造复杂payload,最后发现只需要在末尾加个问号。这让我想起现实中的门禁系统,有人把密码写在便签上贴在显示器边框,保安看见了也不管,因为“那是内部人员才能进来的区域”。
接着往深处挖,hint.php给出了提示:flag在ffffllllaaaagggg文件里。这下思路清晰了,直接用?file=ffffllllaaaagggg试试?不行,因为代码只过滤了source.php和hint.php,其他文件都能正常包含。但问题来了——这个文件在哪?当前目录?上级目录?我试了./ffffllllaaaagggg,没反应。又试../ffffllllaaaagggg,还是空白。直到我把路径写成php://filter/convert.base64-encode/resource=ffffllllaaaagggg,页面才吐出一串Base64编码。
解码之后就是flag。整个过程不到五分钟,但给我的冲击不小。这道题叫warmup,名副其实——它不是为了刁难你,而是想告诉你:安全漏洞往往藏在最不起眼的逻辑缝隙里。那个strpos只检查参数是否包含特定字符串,却忘了URL编码和路径解析的多样性。就像你锁了前门,却忘了后院的小门没插销。
后来我在本地搭环境复现了一遍。把代码抄下来,一行行看,发现那个过滤函数其实只针对$_GET['file']的原始值,而PHP在解析URL时已经做了urldecode。所以%3f在进入代码前就变成了问号,但过滤函数拿到的还是原始编码后的字符串——时间差造成了绕过。这种细节,不亲自调试一遍根本体会不到。
说实话,这道题的技术含量不算高,但它像一面镜子,照出了很多入门者(包括我自己)的思维定式:总觉得漏洞利用要复杂,要各种技巧堆叠。可现实是,大部分漏洞都死于粗心,而非精巧。那个问号,就是开发者脑子里“应该不会有人这么干吧”的念头。而攻防世界的魅力就在于——它把这种念头具象化成一道题,让你在解出来的瞬间,既觉得荒谬,又觉得合理。
最后说点题外的。做完这道题后,我养成了个习惯:看任何代码的过滤逻辑,都会下意识想“如果我在参数里加个编码字符会怎样”。这个习惯帮我发现过不少真实站点的类似问题——虽然都是小漏洞,但小漏洞连起来,就是一条路。warmup教给我的不是某个具体技巧,而是那种“别把防御想得太完美”的警觉。这大概就是它叫warmup的原因吧——热身,热的是脑子,不是手。
