FlawOpen

flawopen.com/Incidents/moveit-transfer-sql-injection-may-2023

● Progress Software · CVE-2023-34362 · May 2023 · CVSS 9.8 · 緊急
セキュリティ研究 · FlawOpen

MOVEit Transfer:SQLインジェクションと大規模なデータ窃取

CVE-2023-34362はMOVEit Transferの認証不要のSQLインジェクションでした。Mandiantは2023年5月27日からの悪用を確認し、その後LEMURLOOT Webシェルの設置とデータ窃取を観測しました。[4], [3]

💡 わかりやすい解説 (ELI5)

「フォルダー番号」欄のあるフォームを想像してください。担当者がその内容を保管システムへの指示文にそのままコピーするとします。入力によって指示文まで変えられるなら、記入者は想定以上の操作をさせられます。SQL インジェクションも同じ境界を越えます。信頼できない入力が値ではなく SQL 構文として扱われます。[5]

主要な概念と専門用語

SQL インジェクション(CWE-89)
データベースへの問い合わせに連結された入力が、値として扱われる代わりに問い合わせの動作そのものを変えてしまうことです。[5]
マネージドファイル転送(MFT)
組織が取引先と大きなファイルや機密ファイルをやり取りするためのソフトウェア。1 台のサーバーに多くの組織のデータが集まり得ます。[3]
Web シェル
攻撃者がアクセスを保つために Web サーバーに仕掛けるスクリプト。今回使われたものを Mandiant は LEMURLOOT と名付けました。[3]
パラメーター化クエリ
値をクエリ本文とは別に送る問い合わせ。データベースがデータを SQL として解釈することはありません。[5]
影響を受けるバージョンと修正バージョン
Progressによると、各ブランチでは2021.0.6、2021.1.4、2022.0.4、2022.1.5、2023.0.1より前のバージョンが影響を受け、これらのバージョンに修正が含まれます。利用中のブランチと現在のアップグレード手順をProgressの勧告で確認してください。[1]

フレームワーク対応

インシデントのタイムライン

2023-05-27

Mandiantは、MOVEit Transferの悪用について自ら確認した最も早い証拠を2023年5月27日として報告しました。[3]

2023-05-31

Progress が脆弱性を公表し、パッチ適用まで HTTP と HTTPS の通信を遮断するよう顧客に求める。[1]

2023-06-02

CISA が CVE-2023-34362 を既知の悪用された脆弱性カタログに追加する。[9]

2023-06-07

CISAとFBIは共同勧告AA23-158Aを公表し、この活動をランサムウェア集団CL0Pによるものと説明しました。Mandiantは後に重複する証拠に基づいて帰属を更新し、UNC4857をFIN11に統合しました。[2], [3]

ステップ・バイ・ステップの攻撃フロー

ステップ 1

認証なしのリクエスト

Mandiantは、LEMURLOOTが確認される前にMOVEit Transferのguestaccess.aspxへ細工したPOSTリクエストが送られていたと観測しました。この活動に通常のユーザーログインは不要でした。[3]

ステップ 2

入力がクエリの意味を変える

リクエストは脆弱なSQL処理に到達しました。CISAは、この欠陥により認証なしでデータベースへアクセスでき、使用するデータベースエンジンによって情報の推測やデータの変更・削除が可能になると説明しています。[2], [5]

ステップ 3

Web シェルが仕掛けられる

悪用後、MandiantはLEMURLOOT Webシェルを確認しました。ファイルの列挙・取得や、特定のアプリケーションユーザーの操作が可能でした。一般的な管理者権限を得たとは資料から確認できません。[3]

ステップ 4

ファイルが大量に盗まれる

Mandiantは大量のファイル窃取を観測しました。CISAとFBIは広範な活動をCL0Pランサムウェアの活動と説明し、Mandiantは後の更新でこの活動をFIN11に関連付けました。[2], [3]

ソースコード比較:脆弱 vs 堅牢化

説明用のC#で、MOVEitのソースコードではありません。強化版のメソッドは識別子を列が実際に持つ型へ変換して、それ以外を拒否し、型付きパラメーターとして送るため、値がSQL本文に入りません。二つの制御のどちらか一方でもこのインジェクションを防げます。両方を使うと、不正な識別子をクエリ実行前に拒否できます。[5]

脆弱な実装
using System.Data.SqlClient;

public static class FolderLookup
{
    public static SqlDataReader Find(SqlConnection conn, string folderId)
    {
        // クエリ文字列とリクエストデータを連結するため、データベースは
        // 開発者がどの部分をデータとして扱うつもりだったか判断できない。
        string sql = "SELECT id, name FROM folders WHERE id = '" + folderId + "'";
        var cmd = new SqlCommand(sql, conn);
        return cmd.ExecuteReader();
    }
}
堅牢化されたセキュアパッチ
using System;
using System.Data;
using System.Data.SqlClient;

public static class FolderLookup
{
    public static SqlDataReader Find(SqlConnection conn, string folderId)
    {
        if (!long.TryParse(folderId, out long id) || id <= 0)
            throw new ArgumentException("folderId must be a positive integer");

        // 値は型付きパラメーターとしてクエリ文字列と分けて渡される。
        var cmd = new SqlCommand("SELECT id, name FROM folders WHERE id = @id", conn);
        cmd.Parameters.Add("@id", SqlDbType.BigInt).Value = id;
        return cmd.ExecuteReader();
    }
}

エンジニアリング&システム堅牢化チェックリスト

参考資料