Citrix NetScaler ADC および Gateway デバイスに対する能動的悪用の防御
MandiantとGTIGはCitrix NetScalerのゼロデイCVE-2026-88772が野外で悪用されていることを発見した。報告書は完全な攻撃チェーン、2つのWebサービス永続化手法、WHIPSHOTとSLAPSHOTの2つのマルウェアの分析、およびハンティングの考え方、3つの対処案とYARAルールを記録している。
日本語
コピー
Citrix NetScaler ADC および Gateway デバイスを標的とした能動的悪用に対する防御
概要
2026年9月下旬、Mandiant Consulting と Google Threat Intelligence Group(GTIG)は、Citrix NetScaler ADC および NetScaler Gateway デバイス上のゼロデイ脆弱性(CVE-2026-88772)が能動的に悪用されていることを確認した。北米および欧州の政府、金融サービス、テクノロジー、教育、法律・専門サービス分野の組織がこの悪用キャンペーンの影響を受けた可能性が高いとみられる証拠を確認している。キャンペーンは少なくとも9月初旬から続いている。ベンダーの開示によれば、脅威アクターは2つ目のゼロデイ脆弱性(CVE-2026-88771)も積極的に悪用している。 CVE-2026-88772 を悪用すると認証をバイパスし、NetScaler Packet Processing Engine(NSPPE)の未処理終了を引き起こすことで、初期の root 権限を確立できる。攻撃者のポストエクスプロイトツールキットを分析した結果、WHIPSHOT など新たに発見されたカスタム PHP Web Shell が判明した。Base64 でエンコードしたコマンド・アンド・コントロール(C&C)ペイロードをネイティブ HTTP ヘッダーに偽装できる。ツールキットには、偵察や資格情報窃取のためにトラフィックを内部ネットワークへプロキシする新しい Python トンネリングツール SLAPSHOT も含まれていた。少なくとも1件の確認された侵害では、脅威アクターがこのプロキシ経由でトラフィックを転送し、手動で内部偵察と資格情報窃取を行っていた。 Citrix は新たに修正された脆弱性に関する顧客向けガイダンスを公開し、こちらで更新するよう推奨している。防御担当者には Citrix のドキュメントを確認し、これらの脆弱性へのパッチ適用を優先することを強く勧める。本ブログの一環として、Mandiant は封じ込めと修復のガイダンスも公開している。
キャンペーンの概要
初期アクセス
初期の認証前暗号ハンドシェイクの過程で、NSPPE は受信した DTLS レコード構造を解析する。Google Threat Intelligence Group はエクスプロイトコードを保有していないが、現場のテレメトリを分析した結果、細工した不正または断片化されたレコードヘッダーを送信すると、パケットエンジン内でヒープメモリの境界破壊が発生し、制御フローが任意の shellcode の実行へと移り、基盤となる FreeBSD プラットフォーム上で root 権限の OS アクセスが得られることが示唆された。 悪用に成功すると、2件のログ記録が生成される。
0-PPE-0 : default SSLLOG SSL_HANDSHAKE_FAILURE 0 : SPCBId - ClientIP - ClientPort - VserverServiceIP - VserverServicePort 443 - ClientVersion DTLSv1.0 - CipherSuite "TLS1-AES-256-CBC-SHA" - Session New - Reason "Handshake failure-Internal Error"
図1:Syslog に記録された SSL ハンドシェイク失敗
qat0: Process <PID> NSPPE-<##> exit with orphan rings 5:500
pitboss[<##>]: pitboss <DATETIME> NOT restarting NSPPE-<##> (<PID>)
図2:FreeBSD カーネルとデバイス watchdog デーモン(pitboss)が記録した NSPPE プロセスの終了(/var/log/messages)
足場の確立と永続化
悪用に成功すると、初期 Web Shell ペイロードは対象の httpd.conf ファイルを改変して自身をインストールし、指定した非スクリプトファイル種別を実行可能な PHP スクリプトとして扱うようシステムを構成する。これにより、WHIPSHOT(PHP Web Shell)や SLAPSHOT(Python プロキシ/トンネリングツール)など、さらなるカスタムマルウェアの配備への道が開かれる。
Web サーバー永続化手法 A:パッケージハンドラ偽装(.deb)
ある事例では、初期インストーラーが /etc/httpd.conf を改変し、Web サーバーが .deb ファイルを PHP スクリプトとして扱うようにした。
php_flag engine on
<FilesMatch "\.deb$">
Header set Cache-Control "no-cache"
</FilesMatch>
AddHandler application/x-httpd-php .deb
図3:パッケージハンドラに偽装した永続化
この構成変更により、攻撃者は /netscaler/gui/vpn/scripts/linux に偽の拡張子を持つ web shell を設置できた。
Web サーバー永続化手法 B:アイコンエイリアスと署名ファイルハンドラ(.sig)
別の侵害では、脅威アクターがより巧妙な構成フックを仕込み、web shell の実行を画像リクエストに偽装した。
php_flag engine on#
AliasMatch ^/vpn/media/(.+).ico$ /var/netscaler/gui/vpn/scripts/linux/$1.sig
AddHandler application/x-httpd-php .sig
図4:アイコンエイリアスと署名ファイルハンドラによる永続化 この構成ディレクティブは3つの処理を行う。
- mod_php エンジンを有効化する。
- .sig ファイルを実行可能な PHP スクリプトとして登録する。
- /vpn/media/ 配下で .ico で終わる受信 HTTP リクエストを、/var/netscaler/gui/vpn/scripts/linux/ 内の同名ベース名に対応する .sig ファイルへ直接マッピングする。
例えば、クライアントが /vpn/media/e6ee7c85.ico にアクセスすると、実際には設置された PHP web shell
e6ee7c85.sigが応答する。少なくとも1件では、Web サーバーのアクセスログに GET リクエストが HTTP 404 を返したと記録されているが、処理時間は長く、レスポンスボディは数千バイトに達していた。その後数日間、攻撃者は存在しない .sig ファイルへのアクセスを試み、httperror-vpn ログにファイル不在エラーを発生させた。これは攻撃者が複数の侵害済み環境で同様の web shell を管理している可能性を示唆する。
Root 権限の永続化
CVE-2026-88772 の初期悪用は root 権限で実行されるが、その後 Web サーバー(httpd)が処理するリクエストは特権のない Web サービスコンテキストで動作する。web shell に永続的な root 権限での実行能力を持たせるため、脅威アクターは軽量インストーラー web shell を使い、/bin/sh 実行ファイルに setuid(Set User ID)ビットを設定した。
chmod u+s /bin/sh
図5:User ID を設定するコマンド
/bin/sh のパーミッションを変更することで、脅威アクターは Web サーバーがその後処理する Web リクエストが昇格した権限で実行されるようにした。SUID shell の変更と同時に /etc/httpd.conf の変更を適用するため、インストーラーは NetScaler デバイスの完全な再起動(/netscaler/nsshutdown -R)を引き起こした。
web shell の別の変種では、脅威アクターが Web サービスを再起動するコマンドを直接送信し、/bin/sh 実行ファイルに root setuid(Set User ID)権限を付与した。
system('/bin/httpd -k restart -f /etc/httpd.conf && chmod u+s /bin/sh');
図6:Web サービスを再起動するコマンド
マルウェア分析
脅威アクターは複数の PHP web shell とトンネリング型マルウェアを配備し、被害組織のネットワークへトラフィックをプロキシして、内部偵察、横展開、資格情報窃取を容易にした。
インストーラーと単体 web shell
Mandiant は複数の軽量 PHP web shell を復元した。これらは .deb および .sig 拡張子のファイルに設置され、直接のコマンド実行と自動化されたデバイス永続化を提供する。直接確認された侵害では、web shell のファイル名は被害者ごとに異なっていた。複数の軽量 web shell の例で、ファイル名に「nginstaller」のさまざまな変種を使用し、その後に通常は数字が続くものを確認した。
- あるサンプルは、コマンドラインインターフェース(CLI)経由で実行されると
/etc/httpd.confを改変し、/bin/shに対して setuid root 権限(chmod u+s /bin/sh)を有効化し、/etc/crontabから/vpn/scripts/linuxへの参照を削除し、/netscaler/nsshutdown -R経由でデバイスを再起動する。HTTP 経由の場合は、HTTP_NSC_LDAPヘッダーから Base64 でエンコードされたコマンドを取り出してshell_exec()で実行し、Base64 でエンコードされた出力を返す。 - 確認されている別の Web Shell 亜種は、偽の HTTP
404 Not Foundレスポンスコードを返す。設定変更を反映させるために Apache デーモン(/bin/httpd -k restart -f /etc/httpd.conf)を再起動し、eval()を使って受信した payload を実行する。検知を回避するため、正規表現(#^.*/vpn/scripts/linux.*\n#m)を用いてシステム/etc/crontabから自身のインストールパスを体系的に消去する。この Web Shell は、HTTP のHTTP_NSC_LDAPヘッダーで受け取った Base64 エンコード済み payload を、PHP のeval()で直接実行する。 - e6ee7c85.sig:同様に
HTTP 404 Not Foundレスポンスを強制する Web Shell 亜種だが、HTTP_NSC_CLIENTTYPEリクエストヘッダーから Base64 エンコードされた payload を取り出し、これもeval()で実行する。
WHIPSHOT
nohup <python> -c 'import base64;exec(base64.b64decode("<payload>"))' /tmp/.uxdport /tmp/.uxdlock > /dev/null 2>&1 </dev/null &
図 7:SLAPSHOT をバックグラウンドで実行するコマンド
- ループバック IPC:SLAPSHOT の起動後、WHIPSHOT は
/tmp/.uxdportに記録された動的 TCP ポートを読み取り、127.0.0.1:との socket 接続を確立して、クライアントのリクエストを転送する。 - 回避:WHIPSHOT は標準エラー出力(
error_reporting(0))を抑制し、HTTP404 Not Foundレスポンスヘッダーを設定するとともに、トンネル経由の TCP レスポンスを HTTP body に入れて返す。
SLAPSHOT
SLAPSHOT は Python で書かれた TCP トンネリングツールである。内部ネットワークのブリッジとして機能し、WHIPSHOT からのコマンドを受け取って、任意の TCP ストリームを内部ホストへ転送する。 主な機能と挙動は次のとおり:
- 動的ポートバインドとロック:起動時に SLAPSHOT は 127.0.0.1 の一時ポートにバインドし、現在のポート番号を指定ファイル(例:
/tmp/.uxdport)に書き込み、fcntl.flock でロックファイル(例:/tmp/.uxdlock)に排他的ファイルロックをかけて、同時に 1 つのインスタンスだけが動作することを保証する。 - 独自のワイヤプロトコル:プロキシとの通信には独自のバイナリプロトコルを使用し、各メッセージは 4 バイトのビッグエンディアン長プレフィックスと、それに続く JSON payload で構成される。対応するコマンドアクションは以下のとおり:
open:対象ホストとポートへのアウトバウンド TCP socket を確立する。push:開いているセッションにデータを書き込む。pull:開いているセッション socket のデータをポーリングして読み取る。exch``:開いているセッション socket に C&C データを送信し、その戻りデータを受信する。close:指定したネットワークセッションを終了する。ping:基本的なヘルスチェック検証を実行する。 アイドルタイムアウト:デーモンは接続アクティビティを監視し、15 分間アクティビティがないと各セッション socket を自動的に閉じる。アクティブなセッションやコマンドを 10 分以内に受信しない場合(UXD_IDLE_EXIT 変数で設定可能)、SLAPSHOT は自身のポートファイルとロックファイルを削除してプロセスを終了し、メモリ使用量と発見されるリスクを最小限に抑える。
影響
今回の作戦は、攻撃者が被害者のネットワークへの初期侵入経路としてエッジデバイスを狙い続けていることを浮き彫りにしている。GTIG は複数の脅威アクターでこの傾向を追跡している。注目すべきは、これらの脆弱性が2025 年の企業関連ゼロデイ脆弱性のおよそ半数を占めることだ。アプリケーションデリバリーコントローラー、VPN ゲートウェイ、ファイアウォールといったこれらのデバイスが常に魅力的な標的であり続けるのは、インターネットに露出し、エンドポイント検知レスポンス(EDR)ツールの対象範囲外にあり、ネットワーク内部への横展開に使える認証情報を保存・処理していることが多いためである。この手法が有効であることが実証されている以上、脅威アクターは今後もエッジデバイスの脆弱性を悪用し続けると予想される。
ハンティング、封じ込め、修復のガイドライン
組織はまず、既存のログと設定ファイルを分析し、侵害の兆候の可能性を発見すべきである。
ハンティング戦略
Citrix NetScaler ADC デバイス
- Web サーバー設定の確認: すべての NetScaler ADC デバイス上の
/etc/httpd.confを確認し、未承認の MIME タイプ、スクリプトハンドラー指令、Web パスエイリアスがないか調べる。AddHandlerやAddTypeが非 PHP ファイル拡張子(.deb、.sig、.html、.rpm、.tgzなど)を PHP スクリプトとして実行するよう登録していたり、AliasMatchが公開 Web パス(/vpn/media/、/vpn/theme/、/vpn/images/)をデバイスのスクリプトディレクトリに向けていたりする場合は、システムが侵害されていることを示す。
grep -En -i "application/x-httpd-php|php_flag|AliasMatch" /etc/httpd.conf
図 8:Web パスエイリアス
- Appliance のステージングディレクトリとクライアントプラグインディレクトリを監査する: ネイティブクライアントプラグインのパス(
/var/netscaler/gui/vpn/scripts/linux/、/var/netscaler/gui/vpns/scripts/vista/、/var/netscaler/gui/vpns/scripts/mac/)と Web リソースのパス(/netscaler/ns_gui/vpn/media/、/var/vpn/theme/)の内容を監査する。これらのディレクトリに置かれる正規のクライアント成果物は、コンパイル済みバイナリまたはアーカイブである。ASCII テキストと判定されたファイルや PHP スクリプトのマーカーを含むファイルはすべて異常とみなす。デフォルトインストールでは、これらのディレクトリには正規のコンパイル済みクライアントバイナリと静的 Web リソースが格納されている。スクリプト以外の拡張子を装ったプレーンテキストのスクリプトや、PHP コードを含むファイルがないか確認する:
file /var/netscaler/gui/vpn/scripts/linux/* /var/netscaler/gui/vpns/scripts/vista/* /var/netscaler/gui/vpns/scripts/mac/* /netscaler/ns_gui/vpn/media/* 2>/dev/null | grep -E "ASCII text|PHP script"
grep -rlE "<\?php|eval\(|base64_decode\(|shell_exec\(" /var/netscaler/gui/ /netscaler/ns_gui/ /var/vpn/ /netscaler/portal/ 2>/dev/null
図 9:クライアント側プラグインのパスを調査し、非スクリプト拡張子を装ったスクリプトや PHP コードを含むファイルを探す
- Web サーバーのアクセスログとエラーログを確認する:
/var/log/httperror*に、偽装された拡張子や非標準の拡張子に関する構文エラー・パースエラー・実行エラーが残っていないか調べる(アクセスログが消去されていても、これらのエラーは残る)。/var/log/httpaccess.logを監査し、静的メディア・アイコン・スクリプトのパスへのリクエストが偽の HTTP 404 や異常に大きなレスポンスボディを返していないか確認する。アクセスログ内で/vpn/scripts/や/vpn/media/の付近に突然現れる時間の断絶や切り詰められた行を検索する。これは、攻撃者の正規表現ベースのログ消去ツールが実行されたことを示している可能性がある。
grep -E -i "\.(deb|sig|rpm|tgz|sh|so|dat|ico|png|html)" /var/log/httperror*
図10:非標準のファイル拡張子を検索して実行
grep -E "/vpn/media/|/vpn/scripts/|/vpn/theme/" /var/log/httpaccess.log* | awk '$9 ~ /200|404/ && $10 > 5000'
図 11:異常に大きなレスポンスペイロードの検索
- 一時 IPC 成果物を確認する:デバイス上の /tmp/ ディレクトリを調べ、SLAPSHOT が作成したロックファイルとポートポインタファイルを探す。
/tmp/.uxdportまたは/tmp/.uxdlockが存在する場合、SLAPSHOT プロキシデーモンが実行中であるか、最近まで実行されていたことを示す。対応担当者は.uxdportに記載されたポートを記録し、sockstat -4 -lでリスニングプロセスを確認する:
ls -la /tmp/.uxdport* /tmp/.uxdlock
図 12:SLAPSHOT が作成したファイルを検索する
- シェルとバイナリのパーミッションを検証する:
/bin/shを確認し、不正な SUID 権限が設定されていないことを確かめる。パーミッションが-rwsr-xr-xで所有者が root になっていれば、そのバイナリは改ざんされており、setuid による権限昇格の永続化に悪用されている。
ls -l /bin/sh
図 13:未授权の SUID 権限を確認する
- プロセス実行とシェル履歴を確認する:システム上で稼働中のプロセスを調べ、バックグラウンドで
/tmp/.uxdportを参照するコマンドを実行している不審な Python インタプリタや、nohupとして動作しているものが存在しないか確認する。/var/log/sh.logを確認し、変更ウィンドウ外で実行された管理系コマンドを洗い出す。強制再起動(/netscaler/nsshutdown -R)や Apache の手動再起動(httpd -k restart)も含める。
ps aux | grep -E "python.*(\.uxd|uxdport|uxdlock|base64)"
図 14:システムプロセス中に異常な Python インタプリタが存在しないか確認する
注意: Citrix は、自社の侵害指標(IOC)スキャンツールを使用して、組織の NetScaler インフラ上の潜在的な侵害指標を特定する方法に関するガイダンスを公開している。詳細は以下の Citrix ドキュメントを参照:
- https://docs.netscaler.com/en-us/netscaler-console-service/instance-advisory/security-advisory-dashboard.html
- https://docs.netscaler.com/en-us/netscaler-console-service/instance-advisory/ioc.html
注意:組織はこれらのハンティング技術を、NetScaler インフラに由来する可能性のある横展開を特定するため、より広範なインフラ全体に適用すべきである。対象は環境全体に及び、他の特権アクセス管理(PAM)プラットフォームを含むがこれに限らない。
封じ込めと修復の戦略
最新のセキュリティ更新を適用していない組織は、ただちに自らの露出面とリスクを評価する必要がある。NetScaler Gateway を大規模にインターネットから隔離したり、厳格な IP 許可リストを適用したりすると、Citrix Virtual Apps and Desktops(旧 XenApp および XenDesktop)経由でリモートワークを支えている組織に深刻な業務中断をもたらす。そのため Mandiant は、パッチ適用を優先しつつ、組織のリスク状況に応じて適切な封じ込め措置と補償的コントロールを実施する、的を絞った段階的なアプローチを推奨する。
即時の緩和措置
組織は以下の選択肢を、自らのリスク許容度、侵害の証拠、運用上の要件に照らして評価すべきである。
オプション 1 — 最新の Citrix バージョンを適用する(Mandiant 推奨)
該当する脆弱性を修正済みの最新 Citrix バージョンを展開する。組織は現在のデプロイブランチに応じて、以下の修正バージョン(またはそれ以降)にアップグレードすべきである:
- NetScaler 14.1 ブランチ:14.1-73.37 以降にアップグレードする。
- NetScaler 13.1 ブランチ:13.1-64.23 および 13.1 のそれ以降のバージョンにアップグレードする。
注意:14.1-FIPS および 13.1-FIPS/NDcPP のデプロイにも対応する修正バージョンがある。
組織が Citrix カスタマーダウンロードポータルで特定のバージョンを見つけられない場合は、Citrix に重大度 1 のサポートチケットを起票し、必要な修正を含む最新バージョンを確認のうえ入手すべきである。
オプション 2 — 侵害された、または侵害が疑われるデバイスを隔離する
侵害が確認された、あるいは疑われる NetScaler デバイスは、ネットワークから隔離する。このオプションは、特にそのデバイスがリモートアクセスやその他の重要なサービスを担っている場合、重大な業務中断を引き起こす可能性がある。 上記のハンティング戦略で侵害指標が検出された場合、Mandiant は以下の封じ込め措置を実施することを推奨する:
- ノードを隔離する。 侵害が確認された、または疑われるデバイスをただちにネットワークから切り離す。
- HA 同期を停止する。 高可用性(HA)ペアで展開している NetScaler では、2 つのノードを個別に評価する。両方のノードが検証を通過するまで設定同期を無効にし、侵害されたノードが悪意ある変更(改ざんされた httpd.conf ファイルなど)をスタンバイノードに複製するのを防ぐ。
- 外向き通信を制限する。 観測された攻撃者インフラをブロックし、当該デバイスの外向きインターネット接続を制限する。特に、任意の外向き TCP/UDP トラフィックを遮断し、明確に必要でない限り TCP/25 経由の外向き SMTP も遮断する。
- ハイパーバイザのネットワーク分離を確認する。 NetScaler が VPX アプライアンスとして仮想化環境上で動作している場合は、vSphere vSwitch と Port Group の設定を確認する。NetScaler VPX が適切にセグメント化され、ハイパーバイザの管理インターフェース(ESXi vmk0 や vCenter など)やその他の機微度の高いインフラ層とレイヤ 2 ネットワークを共有していないことを確認する。詳細な推奨事項は Mandiant の vSphere 向けハードニングガイドを参照。
オプション 3 — 的を絞った補償的コントロールを実施する
ただちにパッチを適用できない場合、組織は的を絞ったコントロールを実施し、影響を受けるデバイスを更新するまでの間、露出する攻撃面を縮小すべきである。以下に示す DTLS および UDP/443 向けのコントロールは CVE-2026-88772 にのみ有効であり、CVE-2026-88771 の緩和をこれらに依存してはならない。両方の脆弱性に対処するには、依然として修正済みの NetScaler バージョンをインストールする必要がある。 A 部分 — ネットワーク制限
- 運用上可能なら DTLS を無効化する。 パッチを速やかに展開できない場合は、インターネットに面した NetScaler Gateway 仮想サーバで、必須でない DTLS を無効化する。今回の攻撃キャンペーンでは、エクスプロイトのペイロードが UDP/443 上でデータグラムトランスポート層セキュリティ(DTLS)を使って配信された。
- 上流で受信 UDP/443 を制限する。 DTLS が明確に必要でない限り、影響を受けるデバイス宛ての受信 UDP/443 トラフィックを遮断する。このコントロールは上流の境界ファイアウォールまたはエッジルータで実施すべきである。NetScaler ローカルの ACL だけに頼ると、トラフィックは脆弱なパケット処理エンジン(nsppe)に到達した後に初めて破棄される。
- 可能な場合は上流で IP 許可リストを実施する。 NetScaler をロードバランシングにのみ使用している組織や、運用する Access Gateway が予測可能な外部送信元 IP アドレスの集合にのみサービスを提供している組織は、上流のネットワーク ACL で未承認のトラフィックを破棄し、デバイスに到達する前に遮断することを検討すべきである。
大量のリモートワーカーを支える公衆インターネット経由の VPN では、動的な住宅用 IP アドレスが運用・管理上の大きな負担となるため、この方法は現実的でない可能性がある。
- フォレンジック分析のために仮想アプライアンスの状態を保持する。 VMware vSphere などの hypervisor 上で動作する NetScaler VPX を含め、仮想アプライアンスとして展開された NetScaler では、運用上許される限り、再起動前にメモリ状態を含む完全な VM スナップショットを作成する。
Part B — 認証情報のローテーションとセッションの終了 侵害されたアプライアンスに保存された認証情報は漏洩したと想定すべきである。認証情報のローテーションとセッションの終了は、当該アプライアンスと接続先システムの間で連携して行う必要がある。
- アクティブなセッションを取り消す。 既存の管理、Gateway、VPN セッションを無効化し、漏洩した可能性のあるセッショントークンを消去する。Citrix Virtual Apps and Desktops のゲートウェイとしてこのアプライアンスを使用している組織は、状況に応じてアクティブな ICA/HDX セッションの終了も行うべきである。詳細なガイダンスは Citrix CTX584227 を参照。
- デバイスキーをローテーションする。 NetScaler 管理者認証情報、ローカルデバイスアカウント、Secure Shell(SSH)キー、TLS 証明書と関連する秘密鍵をローテーションする。
- 統合認証情報をローテーションする。 LDAP bind アカウントとサービスアカウント、RADIUS 共有シークレット、TACACS 認証情報、SNMP community string、NITRO/アプリケーションプログラミングインターフェース(API)認証情報をローテーションする。
- 下流の Citrix インフラストラクチャを監査する。 NetScaler と直接通信するシステム、特に Citrix StoreFront サーバー、Citrix Delivery Controller(DDC)、内部の Citrix Virtual Apps and Desktops ホストを確認する。Windows イベントログを調べ、異常な対話型ログオン、想定外のリモートデスクトッププロトコル(RDP)活動、認証情報ダンプの痕跡、その他の横展開の証拠を探す。
また、侵害されたアプライアンスに保存された TLS 証明書と関連する秘密鍵の失効およびローテーションも検討すべきである。 注意: 認証情報のローテーションは、アプライアンスへのパッチ適用が成功した後に行うこと。
Part C — コントロールプレーンの制限 組織は NetScaler のコントロールプレーンと管理プレーンに追加の制限を課すべきである。
- インターネットに公開するサービスに必要なポートとプロトコルのみを開放する。
- NetScaler アプライアンスにデフォルト拒否のアウトバウンドファイアウォールルールを適用する。
- アウトバウンド接続は、明示的に承認された宛先とサービスのみに許可する。これには DNS、NTP、必要な OCSP/CRL サービス、承認済みのバックエンドアプリケーション、承認済みの管理・セキュリティインフラストラクチャが含まれる。
- 文書化された業務上の必要性がない限り、TCP/25 経由のアウトバウンド SMTP を明示的にブロックする。
- NSIP と管理インターフェースをインターネットに公開しない。
- SSH、HTTPS による管理アクセス、NITRO/API アクセスを、専用の管理ネットワーク、承認済みのジャンプホスト、明示的に承認された送信元 IP 範囲に限定する。
Part D — ログと検知のエンジニアリング 検知は対応戦略の要となる要素である。Mandiant は、必要なテレメトリを利用可能にすることと、ネットワーク・デバイス・ファイルシステム・ID の活動を相関させる検知を実装することの 2 つの側面から検知に取り組むことを推奨する。 ログと可視性 以下の検知のいくつかは、NetScaler がデフォルトでは転送しないログに依存している。検知ロジックを実装する前に、SIEM が次のテレメトリを受信できることを確認する。
- syslog action で転送される NetScaler 監査ログ(ns.log)。SSL 関連のイベントを含む。
- アプライアンスの FreeBSD システムログ(/var/log/messages)。NSPPE の終了・クラッシュや pitboss のメッセージが記録されるが、標準の ns.log 転送には含まれない。
- Web サーバーログ(
/var/log/httpaccess.logと/var/log/httperror*)、NetScaler Web Logging、または AppFlow テレメトリ。TLS はアプライアンス上で終端されるため、上流のネットワーク機器は通常 HTTP リクエストのパスやヘッダーを検査できない。 - NetScaler の NSIP および SNIP アドレスを発信元とするトラフィックのファイアウォールログまたはネットワークフローログ。
- Secret Server などの特権アクセス管理(PAM)の監査ログ。
検知のエンジニアリング
プロトコルとトラフィックの分析
- エクスプロイトの特徴を示す DTLS 失敗にアラートを出す。 ClientVersion が DTLSv1.0、理由が Handshake failure-Internal Error の SSL_HANDSHAKE_FAILURE イベントに注目する。この活動で観測されたエクスプロイトが成功すると、このイベントが生成される。発生のたびに個別に確認し、同一アプライアンスからの集中的な発生を優先する。
- DTLS の失敗とエンジンの終了・クラッシュを相関させる。 同一アプライアンスで一致する DTLS ハンドシェイク失敗が先に発生し、数分以内に NSPPE の終了・クラッシュが続く場合は、エクスプロイトの強い兆候であり、優先度を上げて調査すべきである。
- 想定外のインバウンド UDP/443 を確認する。 DTLS が無効化されている、あるいは本来 DTLS が存在しないはずのアプライアンスに注目する。通常各 Gateway と DTLS 接続を確立する送信元のベースラインを取る。エクスプロイトはごく少量のトラフィックで済む可能性があるため、トラフィックベースの異常検知だけではこの活動を識別できないことがある。
デバイスプロセスとメモリの安定性
- NSPPE の終了・クラッシュを監視する。 NSPPE プロセスの終了やシグナルによる kill を示すカーネルメッセージを検知したら、高重大度アラートを出す。あわせて、/var/core/ 配下に新しい NSPPE コアファイルが作成されていないか監視する。
- pitboss が NSPPE を再起動しない場合にアラートを出す。 pitboss NOT restarting NSPPE を含む pitboss メッセージを監視する。NSPPE のカーネル終了・クラッシュイベントとは別にアラートし、両条件の同時成立は求めない。
- 可用性イベントと突き合わせる。 同じ時間帯にインターネット向け Gateway で予期しない HA フェイルオーバーやデバイス再起動が起きていれば、悪用の傍証と見なす。
ファイルシステムと設定の完全性
- VPN 関連スクリプトのパスを監視する。 VPN 関連ディレクトリ内で .sig ファイルが作成・変更・ステージングされていないか検知する。対象には nsgclient.sig などが含まれ、ディレクトリは例えば次のとおり:
/var/netscaler/gui/vpn/scripts/linux//netscaler/ns_gui/vpn/scripts/linux//var/netscaler/gui/vpns/scripts/vista//var/netscaler/gui/vpns/scripts/mac//netscaler/ns_gui/vpn/media//var/vpn/theme/
Web サーバー設定の不正変更を検知する。 /etc/httpd.conf、/nsconfig/httpd.conf、/flash/nsconfig/httpd.conf が不正に変更されていないか監視する。特に次の場合にアラートを出す:
- AddHandler application/x-httpd-php .[ext] ディレクティブの追加・変更。
- php_flag engine on の設定、その他 PHP 実行を有効にする変更。攻撃者の活動には .php 以外の拡張子を使った PHP Web Shell が含まれ、拡張子は環境によって異なる。/vpn/media/、/vpn/theme/、/vpn/images/ などの Web リソースパスをスクリプトディレクトリや実行ファイルにマッピングする Alias、AliasMatch、RewriteRule ディレクティブ。
ランタイム状態を定期的に確認する。 特に監視すべき点:
/bin/sh に SUID ビットが設定されている
/tmp/.uxdport または /tmp/.uxdlock が存在する
nohup 経由で起動した、あるいは Base64 エンコードされたペイロードを含む Python プロセス
/nsconfig/ 配下の永続化設定や起動ファイルに異常な変更がある
外向き通信とインタラクションの監視
- Web Shell と静的リソース/クライアントスクリプトパスとの不審なやり取りを検知する。 リクエストされたパスだけでなく、挙動そのものに注目する。正規のクライアントも /vpn/media/ 配下のリソースには頻繁にアクセスするためだ。兆候として考えられるもの:
/vpn/media/*.icoまたは/vpn/scripts/へのリクエストが 404 を返すのに、レスポンスボディが数 KB あったり、処理時間が異常に長かったりする。- HTTP エラーログに、
/vpn/scripts/配下で .sig などの非標準ファイルに関する “File does not exist” の記録がある。アクセスログが改変・消去されていても、こうしたイベントは残ることがある。 - httpaccess.log で
/vpn/scripts/または/vpn/media/へのリクエストの前後に、欠落・不正な形式・切り詰められた行がある。
デバイスの異常な外向き通信を特定する。 NetScaler デバイスから直接発信される接続を監視し、宛先が組織承認のホワイトリストにない場合にアラートを出す。特に注目するのは、クレデンシャル保管庫や PAM システムに関わる活動、異常なポート経由のドメインコントローラー接続、短時間での多数の内部システムへの接続、TCP/25 経由の SMTP トラフィック。
侵害指標(IOC)
ネットワーク・トランスポート層の指標
| 種類 | 説明 | 指標 |
|---|---|---|
| 受信ネットワークトラフィック | ゼロデイ脆弱性のエクスプロイトを配信するトランスポートプロトコル | UDP :443 (DTLSv1.0) |
| HTTP リクエストヘッダー | nsginstaller.deb が使う受信コマンド実行リクエストヘッダー | HTTP_NSC_LDAP |
| HTTP リクエストヘッダー | nsgclient.sig が使う受信コマンド実行リクエストヘッダー | HTTP_NSC_CLIENTTYPE |
| HTTP リクエストヘッダー | WHIPSHOT が使う分割 Base64 転送リクエストヘッダー | HTTP_X_UX / HTTP_X_UX_[0-9]+ |
| URI パス | AliasMatch 経由で .sig Web Shell にルーティングされる、アイコンを装ったリクエスト URI | /vpn/media/nsgclient.ico / /vpn/media/*.ico |
| URI パス | NetScaler Gateway 上の悪意ある PHP Web Shell のステージングパス | /vpn/scripts/linux/nsginstaller*.deb/vpn/scripts/linux/nsgclient*.deb/vpn/scripts/linux/*.php |
| IPv4 アドレス | スキャンおよびステージング基盤 | 143.198.7.94 |
| IPv4 アドレス | NetScaler のエクスプロイトと基本的な Web Shell バックドアの設置 | 157.254.167.12 |
より広いコミュニティが本記事で解説する活動を追跡・特定できるよう、GTI Collection では登録ユーザー向けに侵害指標(IOC)を提供しています。
ファイル指標
| ファイルパス | /tmp/.uxdport | SLAPSHOT 活動のポート痕跡 |
|---|---|---|
| ファイルパス | /tmp/.uxdlock | SLAPSHOT プロセスのロック痕跡 |
検出
YARA ルール
rule G_APT_Backdoorwebshell_WHIPSHOT_1
{
meta:
description = "Detects WHIPSHOT PHP webshell tunneling frontend deployed on Citrix NetScaler ADC appliances"
author = "GTIG"
family = "WHIPSHOT"
strings:
// Chunked transport headers
$sh1 = "HTTP_X_UX" ascii
$sh2 = "HTTP_X_UX_" ascii
// IPC lock and port pointers to local proxy daemon
$si1 = "/.uxdport" ascii
$si2 = "/.uxdlock" ascii
$si3 = "/tmp/.uxdport /tmp/.uxdlock" ascii
// Socket forwarding logic
$sf1 = "fsockopen" ascii
$sf2 = "127.0.0.1" ascii
condition:
filesize < 50KB and (
($sh1 or $sh2) and ($si1 or $si2 or $si3) and ($sf1 or $sf2)
)
}
rule G_APT_Tunneler_SLAPSHOT_1
{
meta:
description = "Detects SLAPSHOT Python proxy daemon and tunneling tool deployed alongside WHIPSHOT on compromised NetScaler appliances"
author = "GTIG"
family = "SLAPSHOT"
strings:
// Lock and port files
$ss1 = "/tmp/.uxdport" ascii fullword
$ss2 = "/tmp/.uxdlock" ascii fullword
$ss3 = "UXD_IDLE_EXIT" ascii fullword
$ss4 = "127.0.0.1" ascii
// Wire protocol command verbs
$sc1 = "\"open\"" ascii fullword
$sc2 = "\"conn\"" ascii fullword
$sc3 = "\"push\"" ascii fullword
$sc4 = "\"pull\"" ascii fullword
$sc5 = "\"exch\"" ascii fullword
$sc6 = "\"close\"" ascii fullword
$sc7 = "\"ping\"" ascii fullword
// Protocol parameter names
$sp1 = "\"sid\"" ascii fullword
$sp2 = "\"host\"" ascii fullword
$sp3 = "\"port\"" ascii fullword
$sp4 = "\"data\"" ascii fullword
condition:
filesize < 30KB and (
($ss1 and $ss2 and $ss3) or
($ss4 and ($ss1 or $ss2) and 3 of ($sc*) and 2 of ($sp*)) or
($ss3 and 3 of ($sc*) and 2 of ($sp*))
)
}
rule G_Hunting_Config_NetScaler_PHP_1
{
meta:
description = "Detects unauthorized Apache configuration directives registering non-standard extensions as PHP scripts, or aliasing web paths to appliance script directories on Citrix NetScaler ADC"
author = "GTIG"
strings:
// NetScaler appliance configuration context markers
$ns1 = "/netscaler" ascii nocase
$ns2 = "/var/netscaler" ascii nocase
$ns3 = "/vpn/" ascii nocase
$ns4 = "ns_gui" ascii nocase
$ns5 = "<VirtualHost *:81>" ascii nocase
$ns6 = "Listen 81" ascii nocase
// Generic type or handler registration mapping non-standard file extensions to PHP
// Diversion of web asset paths (media, theme, help, logon, images) to script staging directories
$a1 = "AliasMatch" ascii nocase
$a2 = /\^?\/vpn(s)?\/(media|theme|themes|images|help|logon|support)\// ascii nocase
$a3 = /\/var\/netscaler\/gui\/vpn(s)?\/scripts\// ascii nocase
$a4 = /\/vpn(s)?\/scripts\// ascii nocase
// PHP execution flags
$p1 = "php_flag engine on" ascii nocase
// Exclusions for web pages, markup, and source code
$not_html1 = "<html" ascii nocase
$not_html2 = "<!DOCTYPE" ascii nocase
$not_html3 = "<?xml" ascii nocase
$not_code1 = "package " ascii
$not_code2 = "#include " ascii
condition:
filesize < 100KB and not (
$not_html1 or $not_html2 or $not_html3 or $not_code1 or $not_code2
) and (1 of ($ns*)) and (
// Any directive registering a non-PHP extension as PHP
$t1 or
// Any AliasMatch diverting web paths to script directories
($a1 and ($a2 or $a3 or $a4)) or
// Generic combination of php_flag engine on with script directory aliasing
($p1 and $a1 and ($a3 or $a4))
)
}
rule G_Hunting_Backdoorwebshell_NetScaler_C2Headers_1
{
meta:
description = "Detects standalone PHP webshells deployed on NetScaler appliances extracting commands from custom or native SetEnvIf HTTP headers"
author = "GTIG"
strings:
// NetScaler C2 header patterns (both HTTP_NSC_* and raw NSC_*, covering all native SetEnvIf variables)
$h1 = /(HTTP_)?NSC_[a-zA-Z0-9_]+/ ascii
$h2 = /(HTTP_)?NSC_(USER|NONCE|LDAP|CLIENTTYPE|FT_HIDE)/ ascii nocase
// Specific named NetScaler SetEnvIf headers
$hs1 = "HTTP_NSC_LDAP" ascii fullword nocase
$hs2 = "HTTP_NSC_CLIENTTYPE" ascii fullword nocase
$hs3 = "HTTP_NSC_USER" ascii fullword nocase
$hs4 = "HTTP_NSC_NONCE" ascii fullword nocase
$hs5 = "HTTP_NSC_FT_HIDE" ascii fullword nocase
$hs6 = "NSC_USER" ascii fullword nocase
$hs7 = "NSC_NONCE" ascii fullword nocase
$hs8 = "NSC_LDAP" ascii fullword nocase
$hs9 = "NSC_CLIENTTYPE" ascii fullword nocase
$hs10 = "NSC_FT_HIDE" ascii fullword nocase
// Dynamic execution sinks
$e1 = "eval(base64_decode(" ascii
$e2 = "shell_exec(base64_decode(" ascii
$e3 = "system(base64_decode(" ascii
$e4 = "passthru(base64_decode(" ascii
$e5 = "eval(" ascii
$e6 = "base64_decode(" ascii
$e7 = "shell_exec(" ascii
$e8 = "passthru(" ascii
$e9 = "system(" ascii
$e10 = "exec(" ascii
$e11 = "popen(" ascii
$e12 = "proc_open(" ascii
$e13 = "assert(" ascii
// Concealment and response markers
$c1 = "http_response_code(404)" ascii
$c2 = "REQUEST_METHOD" ascii
$c3 = "<FATO>" ascii
$c4 = "</FATO>" ascii
condition:
filesize < 50KB and (
// Any NSC header accessed alongside dynamic execution
((1 of ($h*) or 1 of ($hs*)) and ($e1 or $e2 or $e3 or $e4 or ($e6 and ($e5 or $e7 or $e8 or $e9 or $e10 or $e11 or $e12 or $e13)))) or
// Any NSC header paired with concealment markers
((1 of ($h*) or 1 of ($hs*)) and ($c3 or $c4 or ($c1 and $c2))) or
// Standalone FATO marker webshell
(($c3 and $c4) and ($e1 or $e2 or ($e5 and $e6) or ($e6 and $e7)))
)
}
rule G_Hunting_Script_NetScaler_Persistence_1
{
meta:
description = "Detects appliance staging, installer, and anti-forensic maintenance scripts deployed during NetScaler compromise"
author = "GTIG"
strings:
// Appliance restart / shutdown commands
$cmd1 = "/netscaler/nsshutdown" ascii
$cmd2 = "nsshutdown -R" ascii
// SUID root backdoor creation
$cmd3 = "chmod u+s /bin/sh" ascii
// Web server reload / restart
$cmd4 = "/bin/httpd -k restart" ascii
$cmd5 = "httpd -k restart -f /etc/httpd.conf" ascii
// Forensic access log scrubbing regex pattern (across any staging path)
$scrub1 = /#\^\.\*\/vpn(s)?\/(scripts|media|theme|themes|help|logon)/ ascii
// Apache configuration modification strings
$cfg1 = "AddHandler application/x-httpd-php" ascii
$cfg2 = "AddType application/x-httpd-php" ascii
$cfg3 = "php_flag engine on" ascii
$cfg4 = "AliasMatch" ascii
$cfg5 = "SetEnvIf" ascii
condition:
filesize < 50KB and (
// Log scrubber + privilege escalation or web server restart
($scrub1 and ($cmd3 or $cmd4 or $cmd5)) or
// SUID root backdoor creation + appliance command or config modification
($cmd3 and ($cmd1 or $cmd2 or $cmd4 or $cmd5 or $cfg1 or $cfg2 or $cfg3 or $cfg4 or $cfg5)) or
// Configuration tampering + appliance command
(($cfg1 or $cfg2 or $cfg4) and ($cmd1 or $cmd2 or $cmd4 or $cmd5)) or
// Generic 2 of the specific appliance maintenance commands
(2 of ($cmd*))
)
}
Google Security Operations
Google Security Operations のユーザーは、以下のルールを利用できます。これらのルールは Mandiant Frontline Threats ルールパックに含まれています。
- SUID or SGID Bit Set on System Shell Binary
- HTTPD Custom Configuration Restart Chained with Permission Modification
- NetScaler Web Directory Suspicious Filewrite
- Python Base64 In-Memory Execution with Hidden Temp File
- Citrix NetScaler Crontab Installation Path Scrubbing
- Citrix NetScaler
ns_monuploadd_err.plLog Poisoning Command Injection - Citrix NetScaler DTLSv1.0 Handshake Failure Internal Error or NSPPE Crash
- Citrix NetScaler Masqueraded Webshell HTTP Request or PHP Error Telemetry
謝辞
本分析は、Bella Valdescruz、Bhavesh Dhake、Chris Linklater、Christopher Romano、Geoff Carstairs、Greg Blaum、Josh Thackston、Kimberly Goody、Lianis Oliva、Matthew Quick、Michael Edie、Omar ElAhdan、Peter Ukhanov、Sagun Chetry、Stuart Carrera、Tyler McLellan の協力によって成し遂げられました。