Swift-Prometheus库安全漏洞解析:未净化指标名称可导致指标导出被篡改

本文详细分析CVE-2024-28867安全漏洞,该漏洞存在于swift-prometheus库中,攻击者可通过未净化的指标名称或标签篡改导出指标格式,导致内存耗尽和服务拒绝攻击。文章涵盖漏洞影响、修复方案和安全建议。

漏洞详情

CVE-2024-28867 是一个中等严重性的安全漏洞,影响 swift-server/swift-prometheus 库。

受影响版本

  • = 2.0.0-alpha.1

已修复版本

  • 2.0.0-alpha.2

漏洞影响

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

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参考实现的方案。

安全讨论

强烈建议不要使用未净化的用户输入作为名称或标签,因为即使此漏洞已修复,仍可能导致指标无限增长,造成拒绝服务攻击机会。

推荐做法

  • 仅使用经过净化的值集合作为指标名称和标签
  • 对于"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/10(中等)
  • EPSS评分: 0.171%(第39百分位)

CVSS v3基础指标

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

弱点分类

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