众所周知,CTF比赛都是人为构造漏洞环境,人为制造安全漏洞,供安全从爱好者研究,好磨练和增强自己的安全技能。
参加CTF比赛,通常你需要明白出题人的想法,按照出题人的意图来解开谜题。
但是,就像所有的游戏一样,在一些未知的地方,总是存在BUG。有时候参赛人员出人意料的行为和动作,会接触到一些从未有人探索过的领域——0day。这是出题人从未预料到的,这就像在一场比赛中参赛者找到了一条比官方航线更好的路线,在一片特别危险的丛林中发现了一个知识宝库。
意外发现的PHP漏洞
我们的故事开始于Realworld CTF比赛,时间为2019年9月14日到9月16日。Wallarm的安全研究员Andrew Danau在攻克一个CTF任务时偶然发现了一个不寻常的PHP交互行为。
当Andrew Danau往URL中插入了%0a
(换行)字符,然后发送给服务器,但服务器的响应很奇怪,它返回的数据比料想的要多,并且这些额外的数据与URL中%0a
之后的字节数有关。
通常来说,这种异常响应与内存损坏有关,这应该是一种信息泄露攻击。这说明它可能会导致敏感数据的泄露。更糟糕的是,尽管没有直接出现,但这种异常行为可能隐藏着远程代码执行。
Andrew没有找到解决这个CTF关卡的方法。他决定和队友就这一不同寻常的发现进行深入研究,希望能够理解其中的缘由,开发成一个远程代码执行漏洞。
这个异常的原因是关于Nginx+fastcgi
的底层,特别是fastcgi_split_path
指令以及涉及换行符的正则表达式的特点。对于%0a
字符,Nginx
会将其设为一个空值,但fastcgi+PHP
不期望这样。
由于Emil对哈希表使用了一些“黑魔法”,所以可以放置任意FastCGI
变量,比如PHP_VALUE
。我强烈建议你通过学习Emil的脚本来了解更多,利用脚本链接[https://github.com/neex/phuip-fpizdam/](https://github.com/neex/phuip-fpizdam/)
。如果你想了解源码,链接在这:
https://github.com/php/php-src/blob/master/sapi/fpm/fpm/fpm_main.c#L1142
以上一切意味着你可以调用任意的PHP代码——在本例中,通过使用Nginx
配置文件中的fastcgi_split_path
指令来处理任何用户的数据,比如URL。
在进一步的调查中,我们在GitHub上发现有大量代码涉及fastcgi_split_path
(超过6千):
https://github.com/search?q=fastcgi_split_path&type=Code
防御方法
在得知Andrew的发现后,我们立刻据此测试了一些安全解决方案,如Wallarm Cloud Native WAF
,并确认Wallarm的WAF能拦截这个漏洞。
而我们在后续研究中也发现可以通过一些简单的方法拦截攻击,比如你正在使用ModSecurity
安全软件,那么就可以通过过滤URL中的%0a/%0d
来防御这种攻击,相关的mod_security
规则如下:
SecRule REQUEST_URI "@rx %0(a|d)" "id:1,phase:1,t:lowercase,deny"
此外我们还建议你通过执行以下简单的bash命令来识别是否可能存在漏洞,它可以识别在你的Nginx配置中是否有错误配置:
egrep -Rin --color 'fastcgi_split_path' /etc/nginx/
最后,在PHP发布相关补丁时,要及时安装。
结论
有时候,思考偏离轨道并不是坏事,Andrew Danau无意中为安全做出了大贡献。我们也相信PHP的开发团队能迅速修复该漏洞。
本文由白帽汇整理并翻译,不代表白帽汇任何观点和立场:https://nosec.org/home/detail/3083.html
来源:https://lab.wallarm.com/php-remote-code-execution-0-day-discovered-in-real-world-ctf-exercise/