后缀漏洞

凌晨三点,后缀漏洞我盯着屏幕上的后缀漏洞“logo.png.php”发呆。攻击者把PHP代码藏在一个图片文件名后面,后缀漏洞服务器居然真的后缀漏洞执行了——就因为我没检查后缀。

这玩意儿叫“后缀漏洞”,后缀漏洞原理简单到让人想骂街。后缀漏洞系统判断文件类型,后缀漏洞不看文件内容,后缀漏洞只看最后一个点后面的后缀漏洞那串字符。你上传一个“shell.php.jpg”,后缀漏洞有些老实的后缀漏洞服务器就会想:哦,这是后缀漏洞图片,放行。后缀漏洞可如果中间某个环节把.htaccess配置错了,后缀漏洞或者解析顺序出了岔子,后缀漏洞那这个“图片”就能变成一把钥匙,直接打开服务器的大门。

我见过最离谱的一次,是在某政府网站后台。对方把“info.asp;.jpg”传上去了,IIS6.0老古董直接按ASP解析。整个上传流程完美无缺,文件头校验、大小限制、路径随机化都做了,就栽在分号上。

这种漏洞最恶心的地方在于,它不挑系统。Windows的IIS有分号截断,Linux的Apache有换行符绕过,Nginx有解析配置错误——每个平台都有自己的小脾气。你以为你在写代码,其实你在跟服务器玩猜谜游戏,猜它到底怎么理解你给的这串字符。

修复方法倒是简单粗暴:别信后缀,看文件头。检查图片的魔数(比如JPEG必须是FF D8 FF),检查MIME类型,更狠的直接用GD库重新渲染一遍图片——就算里面有恶意代码,重新生成后也会被抹掉。但问题是,有多少开发者愿意为这种“小概率事件”多写几十行代码?

有个朋友跟我说,他们公司测试过,把一段PHP脚本改名为任意图片后缀,放到CDN上,结果大部分云存储服务都能正常返回文件内容,只有少数会检查Content-Type。这说明什么?说明整个行业都在裸奔,只不过有人穿了条内裤,有人连窗帘都不拉。

我见过最骚的操作,是有人在文件名里塞了Unicode控制字符。用肉眼看起来完全正常的“photo.jpg”,实际上中间藏了个RTL覆盖符,真实文件名是“photo.php.jpg”。这种攻击连日志都能骗过,你去排查的时候,看到的文件列表全是正常的。

说句实在话,后缀漏洞根本不算什么高深技术,它就是懒。开发者懒得多写几行校验代码,运维懒得改服务器默认配置,厂商懒得修老版本漏洞——层层懒惰叠在一起,才给了攻击者机会。你要是肯花半小时,把上传目录的脚本执行权限关掉,90%的后缀漏洞当场就废了。

但没人做。大家都在赶需求,都在堆功能,谁有空管这种“理论上的风险”?直到某天半夜,服务器被人上传了个“avatar.png”,然后你发现它变成了一个挖矿程序,CPU飙到100%。那时候你才会想起来,原来后缀后面,藏着一整个世界的恶意。