安全工程师盯着那个Steam个人主页看了整整二十分钟,愣是没发现评论区有什么异常。几条看起来正常到无聊的留言,什么"好人一生平安""加个好友一起玩",读起来跟机器人发的都没区别。直到他们把这段文本拖进十六进制编辑器,屏幕上跳出一串不可见字符时,整个实验室安静了。GoDaddy安全团队在本周披露的一场持续数月的攻击活动中,发现攻击者用了一个此前极少在实战中见到的手法:把恶意软件的指挥控制(C2)数据,编码成肉眼不可见的Unicode字符,塞进Steam社区的个人资料评论区。截至目前,已经有大约1980个WordPress网站被植入这种恶意软件。

整个攻击链条的设计思路,用一句话概括就是:你家网站中招之后,会偷偷去翻某个Steam用户的评论区,从那些看似无害的留言里读出下一步该干什么。GoDaddy研究人员在报告中详细拆解了编码方案——攻击者使用了六种不可见Unicode字符来承载有效载荷,分别是零宽度非连接符(U+200C)、零宽度连接符(U+200D)、函数应用符(U+2061)、不可见乘号(U+2062)、不可见分隔符(U+2063)和不可见加号(U+2064)。解码器会忽略所有肉眼可见的字符,只把这六种不可见字符映射成对应的数字,再转换成二进制流,最后重组出字节。GoDaddy在报告中给了一句极其精准的描述,翻译过来是这样的:这套编码机制允许二进制数据被嵌入看起来完全正常的文本里,可见字符充当伪装,不可见字符才携带真正的载荷。

打开网易新闻 查看精彩图片

把Steam当C2服务器用,这招有多刁钻,搞安全的人一眼就能看明白。传统的恶意软件需要在某个VPS或者被控服务器上维护一个控制端,而一旦IP被拉黑、域名被 sinkhole 或者服务器被执法机构接管,整个僵尸网络就瘫痪了。但Valve的平台本身就是全球数千万玩家每天正常访问的基础设施,安全设备和防火墙不可能把Steam的域名一刀切地封掉。攻击者等于把"指挥所"开在了市中心最热闹的商场里,你明知道楼里某张桌子上有人在密谋,但你不能把整栋商场炸了。而且因为评论区本身是公开可读的,恶意软件只需要发一个HTTP请求去拉页面,这种行为混在正常流量里几乎分辨不出来。就算安全人员意识到了问题,去Steam上举报删评论,攻击者换一个账号再发几条就行,边际成本接近于零。

打开网易新闻 查看精彩图片

那黑客到底是怎么把这东西种进网站里的,GoDaddy目前还没法给一个确切答案。研究人员评估了可能的初始入侵途径,范围相当宽:被盗的管理员登录凭证、被泄露的FTP或SSH密钥、某个存在漏洞的WordPress主题或插件被利用,甚至不排除是供应链层面的污染。这个判断的潜台词其实是,攻击者并没有固定的一条路,而是逮到什么用什么。第一阶段植入的恶意软件会利用WordPress的页面加载事件,去访问特定的Steam个人资料页面,提取评论文本并解码,最终拼接出一个指向hello-mywordl[.]info的链接。这个域名下托管着伪装成合法JavaScript库的恶意代码,文件名起得极其讲究——比如asahi-jquery-min-bundle和lodash.core.min.js,任何一个前端开发者在日志里扫到这种名字,第一反应都会认为这是项目依赖的正常加载,不会多看一眼。

载荷执行到最终阶段时,植入的是一个后门。GoDaddy研究人员解释了这个后门的触发机制:它只响应特制的POST请求,而且请求里必须携带一个特定的认证cookie。如果检测到名为tEcaKKXEsb的cookie存在,后门就会通过POST参数接受base64编码的PHP代码并执行。换句话说,就算你发现服务器在往外发请求,如果你没有那个cookie的值,你发过去的指令后门压根不理你。这个设计直接干掉了一大票自动化扫描工具,因为扫描器通常是靠发送已知的恶意payload并观察响应来判断是否存在后门的,人家连门都不给你开,你扫什么。

打开网易新闻 查看精彩图片

GoDaddy还整理了一整套这个恶意软件用到的规避机制,读起来就像在翻一本APT攻防手册。字符串全部用八进制和十六进制转义混淆,函数名每次运行都随机化,代码里甚至塞了假的禁用日志语句来误导分析人员,同时全程使用WordPress原生的API,让自己的行为看起来跟正常的插件或主题调用没有任何区别。对于网站管理员来说,GoDaddy给出了一组自查清单,可以直接照着逐条过:检查代码里是否出现了指向Steam社区页面的URL引用、页面中是否被注入了来源不明的外部JavaScript、服务器是否存在向Steam域名的异常出站连接、以及是否有来自hello-mywordl[.]info等可疑域名的脚本被加载。其他需要警惕的迹象还包括页面源码中出现不可见Unicode字符、WordPress数据库里出现名为_transient_caption_的可疑缓存条目,以及SSL证书验证被手动禁用的情况。