2023年8月4日,于新闻

阅读17分钟

漏洞事后分析:2023 年 7 月

The Metabase Team Portrait
Metabase团队
‧ 2023年8月4日,于新闻

‧ 阅读17分钟

Vulnerability post-mortem: July 2023 Image

在过去的两周里,Metabase 遭遇了该项目有史以来最严重的漏洞。我们知道这个漏洞给您和我们的社区带来了极大的困扰,尤其抱歉的是,我们不得不在一个周五连续两次发布升级通知。

现在,事情基本平息,我们想阐明发生了什么以及我们为何采取了这些行动。我们知道,在没有任何解释的情况下发布“立即升级”的通知是不透明的,需要我们的社区对我们的判断抱有很大的信任。我们希望通过透明地公开所发生的一切(无论是好是坏),社区将继续信任我们。

这个故事的核心是一系列相当恶劣的漏洞,为了更好地理解事件的时间线,了解实际的漏洞至关重要。

温馨提示——这是一篇相当长且技术性较强的文章,主要面向那些管理和保护Metabase的人员。

发生了什么

漏洞详情

这组漏洞的核心是我们支持的一个数据库——H2。H2是一个基于JVM的嵌入式数据库。我们将H2用作Metabase的“开箱即用”数据库,用于存储用户帐户、仪表盘定义、设置等。当我们评估分发示例数据的方法时,H2也成为了首选。作为使用H2分发示例数据库的一部分,我们决定也允许人们连接他们可能拥有的任何H2数据库。它从未被广泛使用,但由于它是“免费附带的”,因此我们很大程度上保留了H2作为受支持的选项。

H2实际上主要用于嵌入到其他应用程序中,因此它有大量未考虑多客户端设计的功能。更具体地说,有一些方法可以使H2在进程内运行解释器,有一些连接字符串参数允许您运行SQL(或任何其他内容),并且通常缺乏针对恶意客户端的加固。我们之前发现并修复了一种利用方式(通过连接字符串上的INIT参数),但最近的漏洞(或实际上是三个不同漏洞的集合)源于此。

存在三个不同的问题

  1. 您可以使用Unicode字符(例如,用“ï”代替“I”)来绕过我们对INIT关键字的检查,因为H2会在内部将其转换(鸣谢 Reginaldo Silva)。
  2. 您可以诱骗Metabase将数据库连接视为PostgreSQL连接,但通过在详细信息负载中偷偷植入H2连接字符串,让JDBC DriverManager加载H2驱动程序(鸣谢长亭科技安全响应中心和bluE0)。
  3. H2中的TRACE_LEVEL_SYSTEM_OUT选项容易受到SQL注入攻击(鸣谢AssetNote和Maxwell Garrett)。

到目前为止,这些问题构成了一组非常烦人的漏洞,它们允许添加或验证新数据库连接的人员入侵运行Metabase的主机操作系统。通常,主机操作系统访问权限仅限于Metabase管理员,因此,虽然这确实是一个问题,但它并非世界末日般的事件。

但还有另外两个关键部分。

首先,人们常常会输入错误的连接字符串,因此在确认某人输入的连接字符串之前进行测试连接是很常见的。我们提供了一个API调用来协助在保存数据库连接之前进行此检查。在通常的管理员面板添加数据库流程中,此操作受API管理员权限检查的保护。

最后也是最令人尴尬的部分是:我们有一个设置过程,可以在一个API调用中创建用户帐户并连接数据库。我们将这两个操作合并为一个步骤,并暴露了一个未经身份验证的API端点/api/setup/validate,它会尝试连接到数据库连接字符串。此端点仅在与setup_token一起使用时才可访问。这个setup_token从未打算公开暴露,通常Metabase会在首次使用后立即删除该令牌。然而,去年年初,我们做了一些更改,允许通过环境变量注入该令牌,并无意中将该令牌泄露到/api/session/properties中暴露的设置中(此外,首次使用后也未能正确清除该令牌)。

这些因素,加上H2在主机操作系统中执行命令的能力,导致了未经身份验证的远程代码执行,并连续两个周五给Metabase社区带来了麻烦。

将所有这些结合起来,攻击者可以

  1. 调用/api/session/properties获取设置令牌。
  2. 使用设置令牌调用/api/setup/validate
  3. 利用缺失的检查,使H2在主机操作系统上执行命令。
  4. 打开反向shell、创建管理员账户等。

简而言之,这是一个极其严重的攻击链。

初步报告和修复(7月13日至21日)

7月13日,我们收到了一位外部研究人员关于应用程序安全漏洞的报告。报告详细说明了上述(非常容易的)路径,无需任何身份验证即可在Metabase服务器中运行自定义代码(我们将此初始漏洞称为“AssetNote”漏洞,因为它是AssetNote团队报告的)。

7月14日,我们已编写、测试并构建了针对此漏洞的修复程序。我们已将其部署到为Metabase云客户托管的2000多台服务器上。

然而,此时我们面临了一个难题:接下来该怎么办?我们有数百家自托管客户,我们有合同和道义上的责任来保护他们。我们还有一个拥有50,000多个在自己的服务器上运行Metabase的组织的社区。一旦知道了漏洞,滥用它就轻而易举;虽然利用该漏洞访问底层数据仓库需要一定的特定技能,但用于DDoS、垃圾邮件和加密挖矿几乎不需要任何技能或精力。我们也没有办法强制任何人升级,甚至无法向那些运行Metabase服务器的人发送电子邮件。

标准的做法是发布补丁,告知全世界这个补丁,并让那些不付费给我们管理服务器的用户自力更生。如果这个漏洞只是一个普通的、不允许任何人随意访问任何Metabase实例上的用户数据的问题,我们就会这样做。

我们真的想做得更好。经过一番思考,我们最终制定了一个三阶段计划。

  1. 向我们的付费客户提供已打补丁的二进制文件。对于运行自定义分支的客户,我们将在保密协议下提供实际的源代码补丁。
  2. 一周后,公开发布不带源代码的修复程序。通知我们的社区这是一个未经身份验证的RCE(远程代码执行)漏洞,并强调立即升级至关重要。
  3. 再过一周后,将修复程序合并到我们的主公共仓库中,并发布CVE,感谢所有帮助我们发现和修复此问题的人。

在这个计划中,我们做出了一个非常具体的权衡。我们知道Clojure JAR文件可以被反编译,反编译后的JVM源代码可以被检查(Clojure通常在JAR中包含源代码)。我们也将已打补丁的二进制文件剥离了这些源代码。在整个发布过程中,我们知道不可能在不让高级研究人员或攻击者了解漏洞是什么以及如何利用它的情况下提供修复。但我们希望在漏洞进入普遍传播之前,尽可能为我们的安装用户争取更多天时间进行升级。

紧急行动并等待(7月18日至21日)

7月18日,我们已部署了打补丁并剥离源代码的二进制文件,并向我们的自托管客户发布了通知。

此初始补丁

  • 如果您已初始化实例(即已完成设置流程),则完全阻止使用该易受攻击的端点。
  • 检测到传递到数据库连接字符串的一些字符串,这些字符串使得第一次攻击可以在/api/setup/validate端点(公开,无需身份验证)和/api/database(私有,需要身份验证)上进行。如果检测到,这些字符串将返回错误,而不是将其传递给H2。

我们与这些客户分享了所有受影响版本的补丁二进制文件,但保留了源代码。对于使用自定义分支的客户,我们要求他们直接联系我们,并在保密协议下向他们提供了补丁。大约有二十名客户运行自定义分支并与我们取得了联系。

目前一切顺利。

接下来的三天里,发生了一些改变我们计划的事件。

观望(7月21日至27日)

我们收到了看似独立的两位客户的报告,他们表示已经知道该漏洞。当时这非常令人惊讶,因为该漏洞已存在一年多才被发现,且利用它需要相当具体地利用我们产品中的一些缺陷。我们深入调查后得知,两位客户都已被发现该漏洞的原始研究团队告知(两位客户都为Metabase安全问题提供漏洞赏金)。

这一点,加上自定义分支的数量,使我们非常担心在没有提前警告或可行的修复二进制文件的情况下,置我们的开源社区于不顾。因此,我们决定加快我们的发布时间表,但仍保留不公开实际漏洞利用的信息。

7月21日,我们发了推文更新了博客在领英上发布了帖子,并向我们Updates邮件列表中的数万名订阅者发送了电子邮件。

我们开始监控社交媒体,看是否有任何情况出现,但几天内都没有任何相关消息,包括在Hacker News上。几天来,虽然有一些关注,但没有人反编译并重现漏洞利用的消息。

7月26日,我们收到了另一份安全报告(此后称为“青”漏洞),报告详细说明了如何通过在连接详情中使用单独的键(而非在同一连接字符串中)来绕过/api/database端点(该端点仅限于经过身份验证的管理员)的控制,以及AssetNote漏洞的一种变体,该变体使用与外部数据库的连接来运行命令。

虽然令人不安,但这些发现都需要已登录的管理员权限,并且只要部署了之前的补丁二进制文件,未经身份验证的RCE就不可能发生。

7月27日,一位工程师(此后称为“Reginaldo”)成功逆向工程了我们的补丁,并在公共/api/setup/validate端点上发现了一种新的攻击。这种攻击利用了变音符号(添加到字母上的字形)来绕过我们已设置的一些控制,但该漏洞仅影响未初始化的实例(处于设置模式的实例),以及另一个也影响/api/database(私有)端点的漏洞,该漏洞会将H2服务器作为外部数据库打开,您可以在其上运行命令。

这稍微提高了风险,因为现在可能对已打补丁的实例进行未经身份验证的RCE攻击——尽管仅限于实例首次设置时的几分钟内。

加速公开版本发布(7月28日至31日)

当天晚些时候(美国时区深夜),第四批安全研究人员未经事先联系我们就发布了一篇博客文章。该文章包含了“AssetNote”漏洞的详细信息,导致AssetNote也公开了他们的发现(因为消息已经泄露)。

7月28日早上醒来,我们看到这篇帖子包含了另一个,“隐藏的”攻击,作者“留给读者去发现”。我们联系了他们,他们告诉我们一种以前未知的通过JDBC DriverManager访问H2的方法。

我们是在构建46.6.3版本(修复“青”和“Reginaldo”漏洞的补丁)的同一时刻得知这种新攻击的。

我们发布了该补丁,但为了保险起见,还决定发布另一个点发布版本(46.6.4),该版本将H2从受支持的分析数据库中移除。由于很明显更广泛的安全社区已经意识到该漏洞的根本原因,我们还发布了一篇博客文章并发送了一封电子邮件,建议我们的客户和开源用户升级,或者在能够升级之前阻止所有相关端点。

在这一切进行的同时,我们为Metabase云客户在自己的服务器上缓解了问题。一旦我们得知每一个漏洞利用,我们立即在所有相关API端点上设置了网络级阻止,关闭了商店的新注册,并开始了审计我们所有日志的“有趣”过程。到周六深夜(7月29日),我们已逐一审计了所有对易受攻击端点有任何调用的服务器,并且没有发现任何篡改证据。我们仍在密切关注任何可疑活动,并就此事件的经验教训进行了大量内部讨论。

7月31日,我们向社区发布了另一条推文和领英帖子。

总而言之,从我们发布通用补丁版本到漏洞广为人知,我们通过混淆努力争取了将近一周的时间。虽然不理想,但希望这能给更多人比原先更多的时间进行升级。

当前状况

TL;DR: 如果您是自托管用户,且上次升级在2023年7月28日之前,请立即升级。

如果您是Metabase云客户,您未受影响。

如果您是自托管用户并正在运行最新的二进制文件(目前为46.6.4),您是安全的。

如果您使用的是Metabase 43-45版本,并且尚未升级到最新的小版本43.7.3、44.7.3、45.4.3或更高版本,则您存在漏洞。

如果您运行的是42或更早版本,则不受此漏洞影响。但您面临许多其他安全问题和错误,因此我们建议您尽快升级。

我们从这次事件中学到了什么?

嗯,我们了解到,如果你发布一个没有任何信息的补丁二进制文件,字节码最多需要五天才能被反编译,然后识别并重新创建底层漏洞。

我们了解到,客户端提供的连接字符串应受到更严格的审查,且JDBC驱动程序不可信任。我们最初特别担心setup_token被用于创建额外的管理员用户,现在我们明白,对于任何打开数据库连接的操作都应该同样警惕。

我们对日志记录、事件响应和入侵检测流程进行了实战演练,并确定了需要改进的领域。

我们仍在进行事后分析,并且无疑在未来几天还会学到更多。

附录

我如何知道我是否受/曾受影响

如果您是Metabase云客户,我们未发现您受到任何影响。我们一收到报告就立即修复并阻止了所有漏洞。我们Kubernetes Pod中的所有实例都已从已知安全镜像回收并重新创建。我们回顾了所有客户数周前的日志,未发现任何可疑的利用迹象。我们将继续监控我们的基础设施,以确保您受到保护。

如果您是自托管Metabase

这些漏洞自2022年5月起就已存在,因此,如果您保存了Metabase实例的日志,或者您的Metabase实例前面有负载均衡器/反向代理,您应该检查以下模式

如果您在日志中看到,在实例初始设置之后任何时间,您收到了对/api/setup/validatePOST API调用,并且该调用返回状态码2xx400,并且您未运行我们于2023年7月18日发布的版本,那么您的实例可能已被攻陷(即:您的实例可能已受到攻击者的控制)。

如何判断攻击者深入程度以及是否有信息被窃取

存在两种攻击类型

  • 如果您看到返回状态码2xx的调用,则您将无法看到攻击者在您的实例上运行了哪些代码,因此您应考虑最坏的情况:攻击者已入侵服务器,获取了应用程序数据库的凭据并能够连接到它,并且他们已窃取了您所连接数据仓库的凭据。
  • 如果您看到返回状态码400的调用,则Metabase日志将打印攻击者在您的实例上运行的代码。例如,

400 status showing the code an attacker could run

从这一点来看,攻击者将能够获取Metabase应用程序数据库的连接字符串,该字符串又包含您数据仓库的连接字符串。

如何判断攻击者是否已打开反向shell

如果您在运行Metabase的服务器或容器中运行top并看到带有参数(如echo、编码参数等)的bash进程正在运行,则该实例已打开反向shell(例如,下图中的PID 3763)。

Instance with reverse shell

如果您在运行Metabase的服务器或容器中运行netstat -antp并看到非Metabase使用的端口有活动连接,且连接处于ESTABLISHED状态(例如,下图中的外部地址172.23.0.2:9001的连接)。

Active connections

如果shell已退出一段时间,您也可能会看到处于FIN_WAIT2状态的连接,例如此示例

Waiting connections

我该怎么办?

如果您怀疑自己可能受到了影响,我们建议您

  1. 使用全新的服务器实例,将您的实例升级到最新的二进制文件。
  2. 轮换您的数据仓库凭据。
  3. 限制未知主机对您数据仓库的IP访问。
  4. 检查您的Metabase实例上是否有不熟悉的 用户账户。
  5. 轮换Metabase中使用的Slack和SMTP凭据令牌。

此漏洞正在被积极利用

我们了解到一些恶意软件开发者/僵尸网络已将漏洞利用代码纳入其攻击中。我们还了解到至少有一个实例攻击Metabase服务器进行加密货币挖矿并使用这些服务器作为DDoS攻击节点。

我们未发现上述端点中存在其他漏洞。

您可能还会喜欢

所有文章
The Metabase Community Data Stack Survey: by data teams, for data teams Image 2025年5月16日,于新闻

Metabase社区数据技术栈调查:数据团队为数据团队而进行

现代数据技术栈如何演变:分享您的技术栈并了解其与其他技术的比较

Margaret Rimek Portrait
Margaret Rimek

阅读2分钟

Product Hunt AMA Recap: embedding, open source success, and more Image 2025年4月7日,于新闻

Product Hunt AMA回顾:嵌入、开源成功等等

在发布之前,我在Product Hunt上主持了一场AMA(Ask Me Anything)活动,并回答了关于Metabase、嵌入、构建开源公司等方面的问题。

Sameer Al-Sakran Portrait
Sameer Al-Sakran

阅读8分钟

所有文章
© . All rights reserved.