一、漏洞简介¶
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 触发条件(如特定模块、特定配置、特定运行环境等)¶
- 用户必须访问 Prometheus Web UI
- 攻击者需要构造特殊的 URL 诱使受害者点击
- Prometheus 实例启用了 Web UI(默认启用)
- 浏览器未启用足够强的 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