警惕!未净化的指标名称与标签可能导致指标导出被劫持

本文详细分析了CVE-2024-28867漏洞,该漏洞存在于swift-prometheus库中。攻击者可通过注入包含换行符等特殊字符的未净化用户输入,来劫持导出的指标格式,导致无限制创建指标、服务器内存膨胀或产生虚假指标。

漏洞详情

CVE-2024-28867 是一个存在于 swift-server/swift-prometheus 库中的中等严重性漏洞。

影响

在将未净化的字符串值直接用作指标名称或标签的代码中,例如:

1
2
3
4
5
let lang = try? request.query.get(String.self, at: "lang")
Counter(
  label: "language", 
  dimensions: [("lang", lang ?? "unknown")]
)

攻击者可以利用此漏洞,通过发送包含换行符、} 或类似字符的查询参数(如 ?lang),来劫持导出的指标格式。这可能导致攻击者无限制地创建存储的指标、使服务器内存使用量膨胀,或产生“虚假”指标。

补丁

库已将默认的标签净化策略移至更深处,防止非法字符出现在名称、标签键和值中。

  • 指标名称 现在必须符合 [a-zA-Z_:][a-zA-Z0-9_:]* 的要求。
  • 指标标签名称 现在必须符合 [a-zA-Z_][a-zA-Z0-9_]* 的要求。
  • 标签值 则不会进行验证,因为它们允许包含任何Unicode字符。开发者必须自行验证标签,不允许恶意输入。

此方法借鉴了Go参考实现的策略。

讨论

强烈建议不要使用未净化的用户输入作为名称或标签,因为它们即使在修补此漏洞后,也可能导致指标的无限制增长,从而造成拒绝服务(DoS)攻击的机会。我们强烈建议仅使用一组经过净化的值作为指标名称和标签。例如,“lang”标签应只使用一组预期的值,并忽略其他值。否则,攻击者可能会为每个不同的标签键创建一个指标,导致必须保存在内存中的指标数量无限制增长,内存使用量随之膨胀。

关于验证标签值:不会自动验证和替换作为标签值提供的字符串。 开发者必须自行验证标签值,并且强烈建议只接受一组已知的值。

可以通过配置 PrometheusSanitizer 来应用您认为必要的验证逻辑:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
let mySanitizer = PrometheusSanitizer { metricName, labels in
  // ... 在此处添加您的逻辑 ...
  (metricName, labels)
}

let registry = PrometheusCollectorRegistry(sanitizer: mySanitizer)
let factory = PrometheusMetricsFactory(factory: registry)

// swift-metrics
MetricsSystem.bootstrap(factory)

缓解措施

开发者必须在使用用户输入作为指标名称、标签名称或值之前对其进行验证。这遵循了不信任任何未经净化的用户输入这一通用安全实践。

致谢

感谢 Jonas Dörr 让我们注意到此问题。

相关信息

安全技术指标

CVSS 总体评分: 5.9(中等) CVSS v3.1 向量: AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:H/A:N

  • 攻击向量: 网络
  • 攻击复杂度:
  • 所需权限:
  • 用户交互:
  • 影响范围: 未改变
  • 机密性影响:
  • 完整性影响:
  • 可用性影响:

EPSS 分数: 0.171%(未来30天内被利用的概率估计)

弱点类型:

  • CWE-74: 输出到下游组件的特殊元素中和不当(注入) 该产品使用来自上游组件的外部影响输入来构建命令、数据结构或记录的全部或部分,但当中继到下游组件时,它没有中和或错误地中和了可能修改其解析或解释方式的特殊元素。
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计