moveit
脅威の調査

更新情報 1: MOVEit Transfer/MOVEit Cloud のゼロデイ脆弱性に関するお知らせ

ファイル転送パッケージ MOVEit のユーザーは、直ちにパッチを適用し、侵害の可能性を示す兆候を確認してください。

** 本記事は、Update 1: Information on MOVEit Transfer and MOVEit Cloud Vulnerability CVE-2023-34362 の翻訳です。最新の情報は英語記事をご覧ください。**

Sophos X-Ops は、MOVEit Transfer および MOVEit Cloud に影響を及ぼす SQL インジェクションの脆弱性に関して、状況の進展を追跡しています。今回関係している脆弱性は CVE-2023-34362 です。

本記事では、SophosLabs および Sophos MDR が確認した脆弱性の概要とガイダンスをご紹介します。今回の脆弱性の詳細が判明するのに従って、脅威と検出のガイダンスなど、本記事を随時更新します。

[2023 年 6 月 9 日 20 時 30 分 (UTC) に公開した最新版には、最新パッチに関する情報および Progress Software が MOVEit のユーザーに向けて発表したガイダンスが含まれます。

2023 年 6 月 6 日 23 時 30 分 (UTC) に公開したバージョン 2 には、「Sophos XDR による影響度の判定」セクションが追加され、IIS ログトレースと合わせて攻撃の件数と多様性に関するデータレイククエリと最新情報を掲載しています。

初版投稿日時: 2023 年 6 月 5 日 22:43 (UTC)]

脆弱性の概要

 

更新後のガイドライン: 2023 年 6 月 9 日現在、Progress は新しいパッチをリリース済みであり、すべての MOVEit のお客様は、最新のアドバイザリの指示に従って、このパッチを適用してください。

2023 年 5 月 31 日に、Progress Software は、攻撃者が MOVEit のインストールを完全に制御できる SQL インジェクションの脆弱性 CVE-2023-34362 に対するパッチをリリースしました。(MOVEit はコンプライアンスに配慮したセキュアなファイル転送・自動化ソフトウェアです。)この脆弱性を利用してアクセス権を取得した攻撃者は、データの改ざんや盗用、Web シェルなどの悪意のあるソフトウェアのインストール、サーバーの設定変更 (新しいアカウントの作成や既存のアカウントの変更) などを実行できます。

オンプレミスユーザー向けの Progress アドバイザリで説明されているように、オンプレミスの MOVEit の全ユーザーは、アドバイザリにある緩和策をできるだけ早く適用し、その後、できるだけ早くパッチを導入してください。MOVEit Cloud のユーザーは、クラウドユーザー向けの Progress アドバイザリのガイダンスをお読みいただき、案内に従ってください。

この脆弱性に対する攻撃は文字通り「ゼロデイ攻撃」であり、パッチが提供される前、あるいは脆弱性が公に開示・議論される前の 2023 年 5 月 27 日の時点で始まっていた可能性が報告されています

また、報告によると、この脆弱性に対する攻撃は、脆弱なシステム上に Web シェルを作成し、そのアクセス権を使用して、侵害されたシステムからデータを盗むことに重点を置いているとのことです。

2023 年 6 月 4 日、Microsoft Threat Intelligence は、今回の攻撃はランサムウェアの操作や Cl0p 恐喝サイトの運営で知られる「Lace Tempest」によるものだと報告しました。Lace Tempest は、業界では FIN11、DEV-0950、TA505 としても追跡されています。

現在までに SophosLabs や Sophos MDR が確認した攻撃の数は限られています。しかし、その被害者は地理的にも業種的にも多様です。他のセキュリティベンダーによる調査でも同様です。また、ソフォスが観測した中で最も早い攻撃は、Progress Software による情報公開の4日前である 2023 年 5 月 27 日に発生しています。

また、ソフォスは、攻撃が成功したことを示す重要な指標として、Web シェル (c:\MOVEit Transfer\wwwroot\human2.aspx) の存在を確認しています。以下の図 1 は、IIS ログに記録された攻撃とそれに続く Web シェルのトラフィックの例です。

An IIS log showing the attempted attack underway

図 1: 進捗中の攻撃

ソフォス製品は現在、この Web シェルを Troj/WebShel-GO として検出し、防御します。

その他にも攻撃の痕跡として、親プロセス w3wp.exe によって生成される csc.exe コンパイラによる「App_Web_.dll」が挙げられます。この dll ファイルには、SQL インジェクションコマンドとハードコードされた Web シェルが含まれており、ソフォス製品によって Troj/WebShel-GO として検出されます。MOVEit をご利用のお客様は、下記の「ガイダンス」の項目で示した案内に従ってください。

特に大事なのは以下の点です。攻撃はパッチが提供される前に始まっているため、未知の方法でパッチ適用前に攻撃が行われた可能性があります。そのため、MOVEit の全ユーザーは公表されている以外の侵害の兆候を確認する必要があります。また、パッチを適用しても、Web シェルやその他の侵害の痕跡は削除されないことに留意してください。したがって、MOVEit をご利用のお客様は、パッチの導入に加え、パッチ導入後のデータ漏洩チェックを行うことが重要です。パッチを適用するだけでは不十分です。

ガイダンス

Sophos XDR による影響度の判定

以下のデータレイククエリを実行すると、MOVEit に関連する csc.exe コンパイラのアクティビティを確認できるため、攻撃の試みを把握することができます。なお、このクエリでは、ソフトウェアのアップデートプロセスでもこの動作が発生するため、無害なアクティビティが返されることもあります。

SELECT
  	   customer_id,
   	   meta_hostname, 
           date_format(from_unixtime(time), '%Y-%m-%d %H:%i:%S') as date_time, 
           time, 
           parent_sophos_pid,
           sophos_pid, 
           parent_name, 
           parent_cmdline,
           username, 
           path, 
           name, 
           cmdline, 
           parent_path, 
           sha1, 
           sha256, 
           company_name,
           file_description,
           file_size,
           file_version,
           is_process_file_signed,
           original_filename,
           product_name
FROM
           xdr_data
WHERE
           query_name = 'running_processes_windows_sophos'
  	   AND LOWER(parent_name) = 'w3wp.exe'
  	   AND LOWER(name) = 'csc.exe'
  	   AND LOWER(parent_cmdline) LIKE '%moveitdmz%'

上記のクエリで不審なアクティビティが見つかり、詳細を確認したい場合には、以下のクエリを実行することで、このプロセスに関する詳しい情報を取得できます。その際には、変数「$$sophos_pid$$」を作成し、前のクエリで使用した Sophos プロセス ID を入力する必要があります。最初のクエリと同様に、アナリストによる分析を必要とする無害な結果も返されることがあります。

SELECT
  	   STRFTIME('%Y-%m-%d %H:%M:%S', 
  	   DATETIME(sophos_process_activity.time, 'unixepoch')) 
  	   AS utc_time,
  	   users.username,
  	   process_journal.parent_sophos_pid,
  	   sophos_process_activity.sophos_pid,
  	   process_journal.path,
  	   process_journal.process_name,
  	   process_journal.cmd_line,
  	   sophos_process_activity.subject,
  	   sophos_process_activity.action,
  	   sophos_process_activity.object,
  	   sophos_process_activity.path,
  	   sophos_process_activity.target_path
FROM
  	   sophos_process_activity
  	   LEFT JOIN sophos_process_journal AS process_journal
		ON process_journal.sophos_pid = sophos_process_activity.sophos_pid
  	   LEFT JOIN users
	        ON users.uuid LIKE process_journal.sid
WHERE  
  	   sophos_process_activity.sophos_pid = '$$sophos_pid$$'
  	   AND sophos_process_activity.action = 'Created'
  	   AND sophos_process_activity.object LIKE '%.dll'

最後に、IIS ログファイルを確認できる場合には、次のクエリを実行して Web シェルのアクティビティを検索することができます。その際には、変数「$$log_path$$」を生成し、確認する IIS ログのファイルパスを入力する必要があります。

 

WITH sorter AS (
WITH content AS 
            --Split the raw log into sortable columns
            (
SELECT 
            -- Grab data from the IIS logs, removing comment lines and limiting returned line count to ensure functionality
                    grep.line
FROM file
     CROSS JOIN grep ON (grep.path = file.path)
     WHERE
                    file.path LIKE '$$log_path$$'
                AND (
                    grep.pattern = 'POST /api/v1/token'
                    OR grep.pattern = 'POST /guestaccess.aspx'
                    OR grep.pattern = 'GET /human2.aspx'
                    OR grep.pattern = 'GET /api/v1/folders'
                    )
            )
            SELECT 
                CAST(SPLIT(line,' ',0) AS TEXT) AS iis_date, 
                CAST(SPLIT(line,' ',1) AS TEXT) AS iis_time, 
                SPLIT(line,' ',2) AS source_ip, 
                SPLIT(line,' ',3) AS cs_method,
                SPLIT(line,' ',4) AS cs_uri_stem, 
                SPLIT(line,' ',5) AS cs_uri_query, 
                SPLIT(line,' ',6) AS source_port, 
                SPLIT(line,' ',7) AS cs_username, 
                SPLIT(line,' ',8) AS remote_ip, 
                SPLIT(line,' ',9) AS user_agent, 
                SPLIT(line,' ',10) AS referer, 
                SPLIT(line,' ',11) AS status,
                SPLIT(line,' ',12) AS substatus,
                SPLIT(line,' ',13) AS win32status,
                SPLIT(line,' ',14) AS timetaken
            FROM content
            WHERE iis_date NOT LIKE '#%'
 
         )
        SELECT
        --CAST(MIN(datetime(iis_date || ' ' || iis_time)) AS varchar) AS first_seen,
        --CAST(MAX(datetime(iis_date || ' ' || iis_time)) AS varchar) AS last_seen,
        datetime(iis_date || ' ' || iis_time) AS timestamps,
        source_ip,
        cs_method,
        cs_uri_stem, 
        cs_uri_query,
        source_port, 
        cs_username,   
        remote_ip, 
        user_agent,
        referer, 
        status,
        CASE 
            WHEN status LIKE '100' THEN 'Continue'
            WHEN status LIKE '101' THEN 'Switching protocols'
            WHEN status LIKE '200' THEN 'OK. The client request has succeeded'
            WHEN status LIKE '201' THEN 'Created'
            WHEN status LIKE '202' THEN 'Accepted'
            WHEN status LIKE '203' THEN 'Nonauthoritative information'
            WHEN status LIKE '204' THEN 'No content'
            WHEN status LIKE '205' THEN 'Reset content'
            WHEN status LIKE '206' THEN 'Partial content'
            WHEN status LIKE '301' THEN 'Moved permanently'
            WHEN status LIKE '302' THEN 'Object moved'
            WHEN status LIKE '304' THEN 'Not modified'
            WHEN status LIKE '307' THEN 'Temporary redirect'
            WHEN status LIKE '400' THEN 'Bad request'
            WHEN status LIKE '401' THEN 'Access denied'
            WHEN status LIKE '403' THEN 'Forbidden'
            WHEN status LIKE '404' THEN 'Page Not found'
            WHEN status LIKE '405' THEN 'Method Not Allowed'
            WHEN status LIKE '406' THEN 'Client browser does not accept the MIME type of the requested page'
            WHEN status LIKE '408' THEN 'Request timed out'
            WHEN status LIKE '412' THEN 'Precondition faile'
            WHEN status LIKE '500' THEN 'Internal server error'
            WHEN status LIKE '501' THEN 'Header values specify a configuration that is not implemented'
            WHEN status LIKE '502' THEN 'Web server received an invalid response while acting as a gateway or proxy'
            WHEN status LIKE '503' THEN 'Service unavailable'
            ELSE 'unknown'
            END AS 'status_def',
        CASE
            WHEN status LIKE '400' AND substatus LIKE '1' THEN 'Invalid Destination Header'
            WHEN status LIKE '400' AND substatus LIKE '2' THEN 'Invalid Depth Header'
            WHEN status LIKE '400' AND substatus LIKE '3' THEN 'Invalid If Header'
            WHEN status LIKE '400' AND substatus LIKE '4' THEN 'Invalid Overwrite Header'
            WHEN status LIKE '400' AND substatus LIKE '5' THEN 'Invalid Translate Header'
            WHEN status LIKE '400' AND substatus LIKE '6' THEN 'Invalid Request Body'
            WHEN status LIKE '400' AND substatus LIKE '7' THEN 'Invalid Content Length'
            WHEN status LIKE '400' AND substatus LIKE '8' THEN 'Invalid Timeout'
            WHEN status LIKE '400' AND substatus LIKE '9' THEN 'Invalid Lock Token'
            WHEN status LIKE '401' AND substatus LIKE '1' THEN 'Logon failed'
            WHEN status LIKE '401' AND substatus LIKE '2' THEN 'Logon failed due to server configuration'
            WHEN status LIKE '401' AND substatus LIKE '3' THEN 'Unauthorized due to ACL on resource'
            WHEN status LIKE '401' AND substatus LIKE '4' THEN 'Authorization failed by filter'
            WHEN status LIKE '401' AND substatus LIKE '5' THEN 'Authorization failed by ISAPI/CGI application'
            WHEN status LIKE '401' AND substatus LIKE '501' THEN 'Access Denied: Too many requests from the same client IP; Dynamic IP Restriction Concurrent request rate limit reached'
            WHEN status LIKE '401' AND substatus LIKE '502' THEN 'Forbidden: Too many requests from the same client IP; Dynamic IP Restriction Maximum request rate limit reached'
            WHEN status LIKE '401' AND substatus LIKE '503' THEN 'Access Denied: the IP address is included in the Deny list of IP Restriction'
            WHEN status LIKE '401' AND substatus LIKE '504' THEN 'Access Denied: the host name is included in the Deny list of IP Restriction'
            WHEN status LIKE '403' AND substatus LIKE '1 ' THEN 'Execute access forbidden'
            WHEN status LIKE '403' AND substatus LIKE '2 ' THEN 'Read access forbidden'
            WHEN status LIKE '403' AND substatus LIKE '3 ' THEN 'Write access forbidden'
            WHEN status LIKE '403' AND substatus LIKE '4 ' THEN 'SSL required'
            WHEN status LIKE '403' AND substatus LIKE '5 ' THEN 'SSL 128 required'
            WHEN status LIKE '403' AND substatus LIKE '6 ' THEN 'IP address rejected'
            WHEN status LIKE '403' AND substatus LIKE '7 ' THEN 'Client certificate required'
            WHEN status LIKE '403' AND substatus LIKE '8 ' THEN 'Site access denied'
            WHEN status LIKE '403' AND substatus LIKE '9 ' THEN 'Forbidden: Too many clients are trying to connect to the web server'
            WHEN status LIKE '403' AND substatus LIKE '10' THEN 'Forbidden: web server is configured to deny Execute access'
            WHEN status LIKE '403' AND substatus LIKE '11' THEN 'Forbidden: Password has been changed'
            WHEN status LIKE '403' AND substatus LIKE '12' THEN 'Mapper denied access'
            WHEN status LIKE '403' AND substatus LIKE '13' THEN 'Client certificate revoked'
            WHEN status LIKE '403' AND substatus LIKE '14' THEN 'Directory listing denied'
            WHEN status LIKE '403' AND substatus LIKE '15' THEN 'Forbidden: Client access licenses have exceeded limits on the web server'
            WHEN status LIKE '403' AND substatus LIKE '16' THEN 'Client certificate is untrusted or invalid'
            WHEN status LIKE '403' AND substatus LIKE '17' THEN 'Client certificate has expired or is not yet valid'
            WHEN status LIKE '403' AND substatus LIKE '18' THEN 'Cannot execute requested URL in the current application pool'
            WHEN status LIKE '403' AND substatus LIKE '19' THEN 'Cannot execute CGI applications for the client in this application pool'
            WHEN status LIKE '403' AND substatus LIKE '20' THEN 'Forbidden: Passport logon failed'
            WHEN status LIKE '403' AND substatus LIKE '21' THEN 'Forbidden: Source access denied'
            WHEN status LIKE '403' AND substatus LIKE '22' THEN 'Forbidden: Infinite depth is denied'
            WHEN status LIKE '403' AND substatus LIKE '501' THEN 'Forbidden: Too many requests from the same client IP; Dynamic IP Restriction Concurrent request rate limit reached'
            WHEN status LIKE '403' AND substatus LIKE '502' THEN 'Forbidden: Too many requests from the same client IP; Dynamic IP Restriction Maximum request rate limit reached'
            WHEN status LIKE '403' AND substatus LIKE '503' THEN 'Forbidden: the IP address is included in the Deny list of IP Restriction'
            WHEN status LIKE '403' AND substatus LIKE '504' THEN 'Forbidden: the host name is included in the Deny list of IP Restriction'
            WHEN status LIKE '404' AND substatus LIKE '0' THEN 'Page Not found'
            WHEN status LIKE '404' AND substatus LIKE '1' THEN 'Site Not Found'
            WHEN status LIKE '404' AND substatus LIKE '2' THEN 'ISAPI or CGI restriction'
            WHEN status LIKE '404' AND substatus LIKE '3' THEN 'Multipurpose Internet Mail Extensions (MIME) type restriction'
            WHEN status LIKE '404' AND substatus LIKE '4' THEN 'No handler configured'
            WHEN status LIKE '404' AND substatus LIKE '5' THEN 'Denied by request filtering configuration'
            WHEN status LIKE '404' AND substatus LIKE '6' THEN 'Verb denied'
            WHEN status LIKE '404' AND substatus LIKE '7' THEN 'File extension denied'
            WHEN status LIKE '404' AND substatus LIKE '8' THEN 'Hidden namespace'
            WHEN status LIKE '404' AND substatus LIKE '9' THEN 'File attribute hidden'
            WHEN status LIKE '404' AND substatus LIKE '10' THEN 'Request header too long'
            WHEN status LIKE '404' AND substatus LIKE '11' THEN 'Request contains double escape sequence'
            WHEN status LIKE '404' AND substatus LIKE '12' THEN 'Request contains high-bit characters'
            WHEN status LIKE '404' AND substatus LIKE '13' THEN 'Content length too large'
            WHEN status LIKE '404' AND substatus LIKE '14' THEN 'Request URL too long'
            WHEN status LIKE '404' AND substatus LIKE '15' THEN 'Query string too long'
            WHEN status LIKE '404' AND substatus LIKE '16' THEN 'DAV request sent to the static file handler'
            WHEN status LIKE '404' AND substatus LIKE '17' THEN 'Dynamic content mapped to the static file handler via a wildcard MIME mapping'
            WHEN status LIKE '404' AND substatus LIKE '18' THEN 'Querystring sequence denied'
            WHEN status LIKE '404' AND substatus LIKE '19' THEN 'Denied by filtering rule'
            WHEN status LIKE '404' AND substatus LIKE '20' THEN 'Too Many URL Segments'
            WHEN status LIKE '404' AND substatus LIKE '501' THEN 'Not Found: Too many requests from the same client IP; Dynamic IP Restriction Concurrent request rate limit reached'
            WHEN status LIKE '404' AND substatus LIKE '502' THEN 'Not Found: Too many requests from the same client IP; Dynamic IP Restriction Maximum request rate limit reached'
            WHEN status LIKE '404' AND substatus LIKE '503' THEN 'Not Found: the IP address is included in the Deny list of IP Restriction'
            WHEN status LIKE '404' AND substatus LIKE '504' THEN 'Not Found: the host name is included in the Deny list of IP Restriction'
            ELSE substatus || ' - Not Defined'
            END AS substatus,
        win32status,
        timetaken    
        FROM sorter

検出の保護

SophosLabs は、悪意のあるドメインをブロックし、以下の検出結果を公表しました。

静的検出:

  • Troj/WebShel-GO

参考資料

より詳しい情報は、Sophos Naked Security (リンク先: 英語) をご確認ください。

謝辞

本記事への協力に対して、Andrew Ludgate、Mark Parsons に謝意を表します。