去年十月,线漏洞一个做跨境电商的线漏洞朋友凌晨两点给我打电话。他的线漏洞独立站挂了,首页被替换成一张黑色背景的线漏洞图片,上面只有一行白字:“你的线漏洞数据库在我手里,48小时内打0.5个比特币过来。线漏洞”
他以为只是线漏洞普通的页面篡改,重装系统就能解决。线漏洞我让他先别动服务器,线漏洞登进后台看了一眼——攻击者留了一个webshell,线漏洞藏在商品评论功能的线漏洞图片上传接口里。这个接口没有校验文件类型,线漏洞上传时改一下Content-Type就能绕过前端限制,线漏洞把PHP文件塞进上传目录。线漏洞文件名伪装成jpg,线漏洞但服务器解析时照样执行。
漏洞本身不复杂。复杂的是它怎么被发现的。
我翻了一遍访问日志。攻击者的IP来自三个不同国家,扫描行为持续了将近两周。前十天都在做一件事:爬取网站所有公开页面的参数结构。商品ID、用户ID、订单号、评论分页——每个URL里的数字和字符串都被记录下来。然后他开始批量替换参数值,观察返回状态码的变化。404说明参数不存在,500说明参数被带进了数据库查询但出错了,200且页面正常渲染说明参数被接受。
这个过程叫参数模糊测试。自动化工具跑起来,一天能试几十万次。朋友的网站用的是三年前某宝买的一套源码,评论模块的图片上传功能压根没做过安全审计。攻击者找到入口后,没有立刻提权,而是先横向移动——从web目录跳到数据库配置文件,拿到数据库账号密码,再通过数据库的LOAD_FILE()函数读取系统文件,最终拿到服务器SSH密钥。
整个过程像入室盗窃。先踩点,再撬锁,进去之后不急着搬东西,先把监控关了、把备用钥匙配好。
我帮他清理完后门、换了密钥、打了补丁。但这件事让我想了很久。大部分中小型网站的安全防线,其实就靠一个“没人会盯上我”的侥幸心理。攻击者根本不认识你,他只是写了一个爬虫,全网扫描带有特定指纹的站点——比如某个CMS的特定版本号、某个框架的默认报错页面、某个插件留下的特征路径。你的网站只要匹配上,就自动进入待攻击列表。
更麻烦的是供应链。朋友那套源码里引用了七个第三方JavaScript库,其中两个已经停止维护超过两年。其中一个库的某个版本存在原型链污染漏洞,攻击者可以通过构造特殊的JSON数据,污染全局对象的属性,进而绕过某些权限校验逻辑。这个漏洞在GitHub上有公开的issue,但源码作者没有合并修复补丁,买源码的人也不会去看依赖库的更新日志。
漏洞从来不是“被黑客发现”的。它一直在那里,只是被某个自动化脚本“匹配”到了。就像一个没锁的自行车,停在路边三个月没人动,不代表它安全,只是还没被路过的小偷注意到。
我给朋友的建议只有一条:把评论模块的图片上传功能直接关掉。他问那用户怎么发图。我说你先把安全做好,再考虑功能。他沉默了一会儿,说好。
后来我偶尔会打开他的网站看看。那个图片上传按钮确实没了。页面加载速度还快了一点。攻击者大概再也不会来了——不是因为防住了,而是因为他的爬虫已经把这个站点标记为“无利可图”。