SVG钓鱼攻击:图片伪装下的恶意脚本与防御指南
我看到这个标题时第一反应是“这种玩法怎么还能一直有效”。SVG 钓鱼并不是什么刚出现的新招但在最近几个月的应急响应里我明显感觉到它的出现频率在上升。原因很简单传统钓鱼附件还有各类伪装但 SVG 这种“看起来是人畜无害的图片”走的完全是另一条路线——它不属于可执行文件却能在打开时执行脚本天然避开了大量安全设备的注意力。SVG 的全称是可缩放矢量图形本质上是基于 XML 的文本格式。这意味着它跟普通图片有本质区别PNG、JPG 被浏览器渲染成位图后就是一堆像素而 SVG 在渲染前先会被解析成一份带结构的文档。攻击者就是看中这一点把恶意代码直接写进 SVG 的脚本节点里。用户双击文件浏览器打开它代码就跑了。更麻烦的地方在于这类攻击在早期很难被一锤子打死。单看 SVG 这个文件它可能只是一段无害的加载逻辑真正干坏事的内容在后续下载的载荷里。这就是我一直说的“前段轻、后段重”的攻击模式——入口文件干净恶意内容动态落地。接下来我把整个攻击链路、样本特征、防御落地和应急排查完完整整拆一遍。1. 一张“图片”为什么会成为攻击入口1.1 SVG 不是普通图片它在浏览器里其实是一段“文档”先补一个基础认知。位图和矢量图的差别大家平时不太注意但在安全视角里这是天壤之别。位图比如 JPG、PNG打开之后就是一个静态的、按像素点排列的数据块。浏览器要做的只是解码、显示没有任何“语义”层面的解析。攻击者在位图里塞东西最多就是隐写术——把数据藏在像素通道或文件尾但想让它自动执行还需要额外找一个解释器去提取。SVG 不一样。SVG 文件用尖括号组织的 XML 结构浏览器会先把它当文档解析再根据其中的标签去渲染图形。在这个过程中SVG 支持内嵌脚本也支持 onload、onclick 这类事件处理器。攻击者只需要一句话一个被浏览器打开的 SVG可以自动执行 JavaScript并且这段 JavaScript 能访问当前页面的 DOM能发起网络请求能调用浏览器暴露出来的各种接口。对攻击者来说这不是“图片”这是一张可以远程控制的木马入场券。我在分析样本时见过的最典型写法是SVG 文件开头是一个看起来完全正常的矢量图形图形中间或尾部嵌入脚本节点然后用 onload 事件触发。整份文件在文本编辑器里看前半段是正常的形状绘制后半段才是真正的恶意逻辑。很多只看文件头的工具根本不会发现异常。1.2 攻击者盯上 SVG 的三个现实理由第一视觉伪装太成功。默认情况下桌面系统的文件夹里 SVG 会显示为图片图标双击后如果默认打开程序是浏览器或者某些支持 SVG 的看图软件用户会觉得“这就是张图”。即便邮件网关或安全软件弹了提醒用户也容易被“一张图而已”的心理预期带偏。标题里说的“特洛伊木马”骗的就是这个信任感。第二检测盲区太明显。大部分传统邮件网关对附件的处理逻辑是看文件扩展名、MIME 类型和特征码。exe、cmd、脚本文件都在重点监控名单里但 SVG 常年不在。发一个 .svg 附件很多网关甚至连“图片类附件白名单”都懒得设。它既不在高危名单里也没有人专门对它做行为分析等于在门口保安的眼皮底下溜进去。第三执行条件太好满足。SVG 打开即执行不需要用户手动启用宏不需要右键管理员运行不需要像某些漏洞利用那样精打细算打补丁。用户只需要按照邮件正文里的提示“双击打开附件”攻击就往前走了一大步。这种一点即中、零交互的执行条件是它比 Office 宏文档更受攻击者欢迎的原因。2. 攻击链路拆解从钓鱼邮件到窃密与挖矿的完整动作2.1 第一阶段伪装与投递攻击者的投递主题几乎都是照着企业真实业务场景抄的。发票确认、物流异常、银行对账单、项目合同回执哪个场景最让员工习惯性点开他们就抄哪个。邮件正文通常写得非常简洁比如“附件是您的最新发票请查收”或“请查看附件中更新后的收货信息”目的就是让收件人没有犹豫地点击。附件后缀是 .svg文件名往往是 invoice.svg、report.svg、shipment.svg 之类。有些攻击者还会在文件名上加两段后缀比如 “invoice.pdf.svg”因为很多系统在显示文件名时只显示最后一部分或者用户默认只注意到前几段根本不会点开属性看完整扩展名。这里有个特别容易骗过老员工的因素企业邮箱如果部署了收发件归档历史邮件里经常有包含 pdf.svg 这类附件的样例邮件系统自己从不拦。时间一长员工就形成路径依赖——“这种附件以前也收过没事”。2.2 第二阶段脚本触发与载荷落地用户双击 SVG桌面系统如果配置的是默认浏览器打开浏览器就会加载整个 SVG 文档。渲染前文档里任何带 onload 的全局事件都会自动触发。恶意代码的第一层通常是少量且故意写得含糊的 JavaScript例如字符串拼接、Base64 解码、字符反转。原因是如果 SVG 里直接放完整攻击代码文件体积会很大也容易被安全沙箱的静态扫描识别。所以攻击者习惯只放一个“下载器”把真正的载荷放在远程服务器上。下载器拿到远程地址后会尝试用 fetch、XMLHttpRequest 或者动态插入 img 标签请求等方式把第二段载荷拉下来。为了躲过代理审计这段远程地址往往不是直接写死的明文而是拆成几个片段在脚本运行到某一步才拼接出来。我在某次事件里看到过地址被倒序处理脚本执行时再逐段 reverse就是为了绕开只看字符特征的安全策略。第二段载荷的落地方式也很有讲究。有的直接是 exe有的先落一个 zip 压缩包再用系统自带的解压命令解出来还有的把载荷伪装成图片文件实际上是一段可执行代码。落地之后攻击者会在脚本里调用系统自带的脚本运行器或命令行工具把这个载荷拉起来。这一步如果成功恶意程序就以完整权限运行起来了。2.3 第三阶段窃密与挖矿组合拳载荷运行起来之后攻击者经常同时部署两条收益线。窃密模块的主要动作是搜集浏览器保存的账号密码、cookie、本地存储数据邮件客户端的通讯录和邮件缓存以及桌面和下载目录里跟财务、合同、账号有关的文档。它还会主动截取屏幕、记录键盘输入在某些环境下会尝试读取聊天工具的本地数据库。数据会被压缩后发送到攻击者控制的服务器整个操作通常会在几分钟内完成因为攻击者清楚传播时间越短被发现和阻断的概率越低。挖矿模块则是长期驻留型。它根据指挥服务器下发的配置在系统空闲或低负载时段启用 CPU 计算把算力用来挖加密货币。这样做的好处是机器平时用起来感觉不到明显卡顿在任务管理器里也不容易看出异常顶多就是 CPU 偶尔占用偏高。攻击者把数据窃取和算力榨取放在一个攻击动作里等于一条攻击链路带来两份收益。这两个模块还经常互相掩护窃密模块负责制造流量和网络连接的“噪音”让安全团队把注意力集中在数据外传上挖矿模块则通过进程伪装、计划任务注册等方式在系统里长期存活。3. 我在样本分析中看到的典型特征3.1 恶意代码的混淆痕迹我分析恶意 SVG 样本时视线第一时间会落在 script 标签的位置和内容上。最常见的特征是 script 标签出现在文件中间偏后的位置而不是视觉图形部分。整份文件在文本编辑器里打开前面的路径命令都是正常的M、L、C这类矢量绘制指令突然出现一段与图形无关的 JavaScript这就是强信号。另一个特征是代码几乎都经过混淆。我见过用 Base64 套一层、再把字符串倒序的也见过用字符串数组加索引取值来躲避特征匹配的。还有一类样本会在脚本里反复调用 unescape 或 fromCharCode把十六进制编码还原成可读代码。这类混淆本身没有太高难度但对付只看裸字符特征的传统杀毒引擎绰绰有余。3.2 容易被忽略的“图片加载”细节有一类 SVG 样本攻击者给它包了一个看起来完全正常的图形外壳。外壳里的内容经常是公司 logo、快递单样式或者某个网站的登录界面截图。这份“图片”之所以叫图片就是因为这部分绘制逻辑写得挺认真。但外壳底下还藏着别的。比如某些 SVG 会嵌入外部实体引用也就是 XML 的实体扩展功能。攻击者可以利用这个读取本地文件比如在浏览器解析时把系统里的某个敏感文本文件内容拼进图片属性里再回传。这就是典型的 XXE 攻击思路。再比如有些 SVG 用onerror或onload触发脚本后脚本第一件事不是下载载荷而是检测运行环境。它会检查当前是否有调试器、是否运行在无头浏览器里、网络请求是否超时。如果环境不对脚本就直接做图片渲染啥也不干。这种“环境感知”逻辑让很多自动化沙箱拿不到后续载荷。3.3 沙箱检测为何会漏我见过不止一个安全产品给出的检测结论是“未发现恶意行为”。这不是产品能力不行而是这类攻击天然挑环境中挑时机。沙箱里打开 SVG很常见的情况是沙箱直接拿图片解析库去读取文件根本不触发浏览器渲染。即使触发了浏览器如果沙箱不具备网络外联能力或者攻击者用了“首次访问需要带特定 Cookie 或令牌”的逻辑真实载荷根本不会响应。更狡猾的手段是延迟请求。脚本在 SVG 打开后先等几分钟等沙箱的静态扫描和动态分析基本结束后才开始外连。有些沙箱的超时判断是 60 秒攻击者把延迟改成 120 秒就成功地躲了过去。这也是我一直在强调的只看单文件、单次行为很难完整还原攻击。必须把邮件、文件、进程、网络请求串联起来看才能发现真正的恶意链路。4. 企业环境里的检测与防御落地4.1 邮件网关与客户端的两道关口把 SVG 附件直接禁止是成本最低、效果最明显的入口管控方案。邮件网关里可以在附件类型策略里增加一条规则所有 .svg、.svgz 后缀的附件一律拦截或者在放行前强制转成安全格式。如果业务上确实有接收矢量图的需求可以让用户通过公司内部的网盘或文档系统传输不走邮件附件通道。客户端侧可以统一调整默认打开方式。SVG 文件的默认打开程序从浏览器改成纯文本编辑器或一款不执行脚本的图片查看器。这样即便用户手动打开看到的也是源代码而不是“可执行图片”。虽然这种做法会影响正常的图片预览体验但对安全目标明确的团队来说这点牺牲是值得的。还有一道容易被忽略的关口是即时通讯工具和内部文件共享。攻击者会通过邮件拿到第一个入口但同样会用即时通讯把恶意 SVG 传给指定的人。这类通道往往没有邮件网关那么成熟需要靠终端策略补上。4.2 终端侧的行为监控策略终端安全软件能不能拦住这类攻击关键不在于有没有“查杀 SVG”的特征库而在于行为监控做得到不到位。我建议监控这些行为点浏览器进程启动后 5 秒内又拉起一个新的进程而且这个新进程不是常见子进程要重点记录。系统自带的脚本解释器在短时间内从浏览器进程的目录下执行文件或者从临时目录执行东西要触发告警。进程访问冷门域名或 IP尤其是刚注册不久、无备案、不常见端口号的外联要记录完整请求。计划任务新增、启动项写入、注册表自动运行键被改动这些动作发生在非安装时间的也要关注。把监控点定在这些行为上恶意 SVG 的下载和执行链条就能被拆开。攻击者可以藏住文件特征但藏不住行为特征——他要下载载荷就要发起网络请求要执行载荷就要启动子进程要持久化就要写启动项。这三步只要有一步被监控到就有机会把攻击按死在半路。4.3 员工安全意识教育的具体切入口很多安全团队在意识教育上只会说“不要点陌生邮件”“不要打开可疑附件”。这种话讲多了员工就麻痹了。更有效的做法是用实际攻击场景做案例复盘。比如你可以组织一次内部钓鱼演练邮件主题就是“本月工资条调整通知”附件就是一个 SVG 格式的“工资条”。员工点击后页面跳到一个“密码已过期请重新认证”的提示。后台记录下点击和输入行为然后安全团队逐个部门公布结果。这种演练比十次幻灯片宣讲都管用。在平时培训里至少要让员工建立两个具体认知第一邮件附件如果不是日常固定接收的类型一定要先看完整文件名确认扩展名第二任何要求“双击打开”“启用内容”“重新认证”的附件都要先咨询安全团队。把这些话放到具体场景里讲员工才能真正记住。5. 应急响应与排查思路5.1 发现可疑文件后先做什么如果安全团队收到员工上报说“打开附件后电脑突然卡顿风扇转得很快”先不要急着清理文件先把现场留好。第一步让员工断开网络连接但不要关机。断网能切断恶意载荷继续下载或外传数据的通道不关机是为了保留内存里的攻击痕迹。第二步把可疑 SVG 文件复制到一个单独的隔离目录保留原件。随后用文本编辑器打开这个 SVG重点搜几个关键词onload、onerror、script、>