游客发表
去年秋天,漏洞略我帮一个做电商的消除朋友排查服务器。他的漏洞略站点跑在一台老旧的CentOS 7上,PHP 5.6,消除数据库还是漏洞略MySQL 5.5。用他的消除话讲,“能跑就别动”。漏洞略结果某天凌晨,消除支付接口被注入了恶意脚本,漏洞略用户下单后跳转到一个钓鱼页面。消除损失不大,漏洞略但足够让他连夜打电话把我叫起来。消除
问题出在一个不起眼的漏洞略文件上传功能上。代码里用$_FILES['file']['type']判断文件类型,消除这玩意儿客户端随便改。漏洞略攻击者传了个.php.jpg,服务器直接当PHP执行了。漏洞本身不复杂,但消除它的过程,远不是改一行代码那么简单。
很多人一上来就想着打补丁、上WAF。我习惯先翻日志。那次我让他把Nginx的access.log和PHP的错误日志都导出来,用grep筛了半小时。发现攻击者第一次试探是在三周前,传了个test.php,返回200。之后每隔两天就换一个文件名来试。真正得手那次,用的是avatar.php%00.jpg——空字节截断,老PHP版本的通病。
你看,漏洞不是突然出现的。它一直在那儿,只是没人去碰。消除漏洞的第一步,是承认它存在,并且找到它被利用的路径。别急着封IP,先看攻击者怎么进来的。
朋友一开始想让我装个安全插件了事。我拒绝了。那个上传功能的核心逻辑是:接收文件→检查后缀→移动文件。问题在于检查环节用了不可靠的输入。正确的做法是白名单——只允许jpg、png、gif,并且用finfo_file()读文件的真实MIME类型,而不是信任浏览器传来的type。移动文件后,还要把上传目录的PHP执行权限关掉。Nginx里加一行location ~* /uploads/.*\.php$ { deny all; },比什么插件都管用。
改完这些,我让他把PHP升到7.4,MySQL升到8.0。他心疼那台老机器,我说你心疼机器,攻击者可不会心疼你的用户数据。升级过程中果然又炸出两个兼容性问题,一个是mysql_connect弃用,另一个是ereg正则被移除。这些老函数本身就是漏洞温床,早该扔掉。
漏洞修完了,不代表事情结束。我让他在代码仓库里加了个pre-commit钩子,任何提交如果包含$_FILES或eval(就自动告警。又配了个简单的日志监控脚本,一旦/uploads/目录下出现.php文件就发邮件。上个月他告诉我,脚本拦了三次尝试,都是自动扫描器干的。
还有个细节:他之前把所有错误信息都显示在前端,display_errors = On。攻击者能看到完整路径和数据库结构。我让他关掉,改成写日志。这不算漏洞,但属于“漏洞消除”的一部分——减少信息泄露,就是减少攻击面。
现在他的站点跑在PHP 8.1上,用了Laravel的验证规则,上传目录挂载在独立分区,权限是www-data:www-data,755。他说感觉像换了辆车。我说不是换车,是把刹车片和安全带都装上了。漏洞不会自己消失,你得动手拆掉它,再把拆下来的零件扔远点。
最后提一句:别信“一键修复”工具。我见过太多人跑完扫描器,看到“0漏洞”就安心睡觉。真正的漏洞消除,是理解每一行代码为什么这么写,以及攻击者会怎么绕过去。这活儿没有捷径,但有方法。方法对了,剩下的就是耐心。
随机阅读
热门排行
友情链接