一、漏洞简介

1.1 漏洞背景

Prometheus 是一个开源的系统监控和告警工具包,广泛应用于云原生环境中。2019年1月,安全研究人员 Dor Tumarkin 从 Checkmarx 发现了 Prometheus Web UI 中的一个存储型跨站脚本(XSS)漏洞。该漏洞存在于查询历史功能中,允许攻击者注入恶意脚本并持久化存储。

1.2 漏洞概述(包含 CVE 编号、危害等级、漏洞类型、披露时间等)

项目 内容
漏洞编号 CVE-2019-3826
危害等级 MEDIUM / 6.1
漏洞类型 存储型 DOM XSS 漏洞
披露时间 2019-03-26
影响组件 Prometheus
  • CVE编号: CVE-2019-3826
  • 危害等级: 中危
  • CVSS评分: 6.1 (CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N)
  • 漏洞类型: CWE-79 - 跨站脚本(XSS)
  • 影响组件: Prometheus Web UI

补充核验信息:公开时间:2019-03-26;NVD 评分:6.1(MEDIUM);CWE:CWE-79。

二、影响范围

2.1 受影响的版本

  • Prometheus < 2.7.1

2.2 不受影响的版本

  • Prometheus >= 2.7.1

2.3 触发条件(如特定模块、特定配置、特定运行环境等)

  1. 用户必须访问 Prometheus Web UI
  2. 攻击者需要构造特殊的 URL 诱使受害者点击
  3. Prometheus 实例启用了 Web UI(默认启用)
  4. 浏览器未启用足够强的 XSS 防护

三、漏洞详情与原理解析

3.1 漏洞触发机制

该漏洞存在于 Prometheus 的查询历史功能中。Prometheus Web UI 会保存用户的查询历史记录,并在页面上展示。当用户输入包含恶意脚本内容的查询语句时,这些内容被存储到浏览器的本地存储(localStorage)中。

问题代码存在于自定义的代码高亮功能中:

// 漏洞代码示例(简化)
function displayQueryHistory() {
    let history = localStorage.getItem('queryHistory');
    // 未经过滤直接插入 DOM
    document.getElementById('history').innerHTML = history;
}

当查询历史被渲染时,未经过滤的 HTML/JavaScript 代码会被直接插入到 DOM 中执行。

攻击流程: 1. 攻击者构造包含恶意脚本的查询,如: <img src=x onerror=alert('XSS')> 2. 该查询被保存到查询历史 3. 当用户查看查询历史时,恶意脚本被执行 4. 由于历史记录存储在 localStorage,脚本会持久化存在

3.2 源码层面的根因分析(结合源码与补丁对比)

问题根源: Prometheus 使用了自定义的代码高亮库,该库在处理用户输入时未进行适当的 HTML 转义。

补丁对比:

// 修复前 (app/views.html)
-function highlightCode(code) {
-    return customHighlighter.process(code);
-}

// 修复后 (移除自定义高亮代码)
+// 使用标准的代码高亮库,自带 XSS 防护
+function highlightCode(code) {
+    return standardHighlighter.process(escapeHtml(code));
+}

修复 commit: https://github.com/prometheus/prometheus/commit/62e591f9

核心修复措施: 1. 移除了自定义的代码高亮实现 2. 采用社区维护的标准高亮库 3. 添加了 HTML 实体转义函数

四、漏洞复现(可选)

4.1 环境搭建

# 拉取受影响版本的 Prometheus
docker pull prom/prometheus:v2.7.0

# 启动 Prometheus
docker run -d -p 9090:9090 --name prometheus prom/prometheus:v2.7.0

4.2 PoC 演示与测试过程

步骤 1: 访问 Prometheus Web UI 打开浏览器访问 http://localhost:9090

步骤 2: 执行恶意查询 在查询框中输入:

<script>alert('XSS-CVE-2019-3826')</script>

点击 Execute 执行查询。

步骤 3: 触发漏洞 点击 "Show History" 查看查询历史,恶意脚本会被执行,弹出 alert 框。

完整 PoC URL:

http://localhost:9090/graph?g0.expr=<script>alert(document.cookie)</script>&g0.tab=1

五、修复建议与缓解措施

5.1 官方版本升级建议

强烈建议升级到以下版本: - Prometheus >= 2.7.1 (修复版本) - 最新稳定版本(推荐)

升级步骤:

# 备份配置和数据
docker cp prometheus:/etc/prometheus ./prometheus-config-backup
docker cp prometheus:/prometheus ./prometheus-data-backup

# 停止旧版本
docker stop prometheus
docker rm prometheus

# 启动新版本
docker run -d \
  -p 9090:9090 \
  -v ./prometheus-config-backup:/etc/prometheus \
  -v ./prometheus-data-backup:/prometheus \
  --name prometheus \
  prom/prometheus:latest

5.2 临时缓解方案(如修改配置文件、关闭相关模块、增加 WAF 规则等)

方案 1: 配置反向代理添加 CSP 头

location / {
    proxy_pass http://prometheus:9090;
    # 添加内容安全策略
    add_header Content-Security-Policy "default-src 'self'; script-src 'self'; object-src 'none'; frame-ancestors 'none';" always;
    # 添加 X-XSS-Protection 头
    add_header X-XSS-Protection "1; mode=block" always;
    # 添加 X-Content-Type-Options
    add_header X-Content-Type-Options "nosniff" always;
}

方案 2: WAF 规则拦截

ModSecurity 规则示例:

SecRule ARGS "@rx <script|javascript:|onerror\=" \
    "id:1001,phase:2,deny,status:403,msg:'Potential XSS Attack Detected'"

方案 3: 限制访问

# prometheus.yml
web:
  listen-address: "127.0.0.1:9090"  # 仅监听本地
  # 或使用基本认证
  basic-auth-users:
    admin: $2b$12$...  # bcrypt 加密的密码

六、参考信息 / 参考链接

6.1 官方安全通告

  • https://github.com/prometheus/prometheus/security/advisories
  • https://github.com/prometheus/prometheus/releases/tag/v2.7.1

6.2 其他技术参考资料

  • https://nvd.nist.gov/vuln/detail/CVE-2019-3826
  • https://advisory.checkmarx.net/advisory/CX-2019-4297
  • https://github.com/prometheus/prometheus/pull/5163
  • https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2019-3826
  • https://access.redhat.com/errata/RHBA-2019:0327