php文件上传漏洞
一个webshell砸进服务器,传漏往往不是传漏因为代码写得多精妙,而是传漏因为上传功能太信任用户。PHP文件上传漏洞,传漏说白了就是传漏开发者默认所有提交上来的文件都是善意的,可互联网上从来不缺想试试你底线的传漏人。
拿个最简单的传漏例子说。某后台有个头像上传功能,传漏前端校验了jpg、传漏png后缀,传漏后端也校验了MIME类型。传漏你以为这就安全了?传漏攻击者抓个包,把文件名改成shell.php.jpg,传漏再把Content-Type改成image/jpeg,传漏服务器端如果只查MIME和扩展名白名单,传漏这文件就存下来了。存下来之后配合一个解析漏洞,比如Apache的Unknown后缀解析,或者Nginx配置不当导致的%00截断,直接就能把这段PHP代码跑起来。整个过程不到五分钟,你辛辛苦苦搭的站就成了别人挖矿的肉鸡。
更讽刺的是,很多框架自带安全函数,但开发者不用。move_uploaded_file()只是移动文件,它不关心文件内容是什么。真正该做的是检查文件内容头几个字节,比如图片的GIF89a,PDF的%PDF,再用getimagesize()或finfo_file()这类函数确认真实类型。可大多数新手教程里只教你查扩展名,查MIME,这俩全都能骗。我见过某知名CMS的旧版本,就是只查了$_FILES['file']['type'],这玩意儿是客户端传过来的,改个请求头的事,等于没设防。
还有个容易忽略的坑——文件存储路径。如果你把上传的文件直接放在web根目录下,访问路径就是公开的。攻击者上传一个正常图片,里面嵌着一句话木马,然后用文件包含漏洞去调用它,或者利用服务器对.phar、.phtml这类扩展名的解析顺序差异。之前有个真实案例,某个招聘网站允许上传简历附件,只过滤了.php,没过滤.php5、.phtml、.pht,结果被人上传了.phtml后缀的木马,直接拿到了服务器权限。这类变种后缀在Apache的默认配置里经常能被解析,因为AddHandler里写的是application/x-httpd-php .php .phtml .php5。
你可能会问,那我把上传目录设成不可执行不就行了?对,这招确实能挡掉大部分攻击。给上传目录设置php_admin_flag engine off,或者用.htaccess禁止PHP解析,这比过滤文件名可靠得多。但很多人忘了,如果上传目录和可执行目录是同一个虚拟主机上的不同alias,或者你能通过路径穿越符号链接绕过去,那这层防护也白搭。
说到底,这漏洞的本质是信任边界没划清楚。用户输入的东西,不管是文件名、内容还是类型,全是不可信的。你得假设每个上传请求都是来搞破坏的,然后从代码层面一层层剥掉攻击面。检查扩展名用白名单,别用黑名单;检查内容用文件头签名,别信MIME;存储路径扔到public目录之外,再用随机文件名重命名,别保留用户原始文件名。做到这三条,基本能堵住九成以上的上传漏洞。
剩下的那一成,靠的是及时更新服务器和框架补丁。毕竟攻击者也在研究新绕过技巧,比如利用图片的Exif信息藏代码,或者用phar://协议反序列化。安全这活儿,永远是在跟时间赛跑。你懒一天,漏洞就多活一天。