NTT Security Japan

お問い合わせ

React2Shellによって実行されるマルウェアZnDoorについて

テクニカルブログ

React2Shellによって実行されるマルウェアZnDoorについて
本稿では、実際に日本国内の企業で観測されたReact2Shell悪用事例と、マルウェアZnDoorの解析結果を共有します。

本記事はSOCアナリスト 野村和也が執筆したものです

はじめに

SOCでは2025年12月から、日本国内においてReact2Shell(CVE-2025-55182)を悪用したインシデントを多数観測しています。それらの多くはコインマイナーなどが実行されていますが、中には未知のマルウェアが実行されるケースも存在します。

 私たちは今回発見した未知のマルウェアをZnDoorと名付け、調査を行いました。ZnDoorは少なくとも2023年12月には使用されていた可能性があり、ネットワーク機器の脆弱性悪用事例と関連があると推察されます。

本稿では、実際に日本国内の企業で観測されたReact2Shell悪用事例と、マルウェアZnDoorの解析結果を共有します。

攻撃フロー

本攻撃の起点となったReact2Shellは、React / Next.jsに存在するリモートコード実行の脆弱性です。既にPoCが公開され、多くのWebサービスが被害を受けており、大きなインパクトを与えています。SOCにおいても、React2Shellを悪用した攻撃を多数観測しています。

ZnDoorが実行される際の攻撃フローは以下のとおりです。

まず、React2Shellの脆弱性が悪用され、以下のコマンドが実行されます。

これによって外部からZnDoorがダウンロード・実行されます。ZnDoorは実行されるとC2サーバと通信を行いますが、そのC2サーバはZnDoorが置かれていた配信サーバと同一でした。

Configデータ

本検体のConfig情報は、`src/structsInfo.InitInfo`  関数に記載されており、Base64にて復号後、AES-CBCで復号が可能です。


Config情報として、以下の文字列が暗号化されて埋め込まれています。

- I6ACRtPz1zjcpsxLoAyGdA==#api.qtss[.]cc
- DzPe8oPOSSTqDKvfftVsYw==#443

また、C2と通信するURL構築を`src/structsInfo.InitInfo` 関数で行います。

- http[:]//api.qtss[.]cc:443/en/about?source=redhat&id=v1.0/en/about?source=redhat&id=v1.1
- http[:]//api.qtss[.]cc:443/en/about?source=redhat&id=v1.1
- http[:]//api.qtss[.]cc:443/en/about?source=redhat&id=v1.21136868377216160297393798828125

定常通信

本検体の関数znF0q.Kは、システム情報をJSON化し、定期的にC2にPOSTします。

キー

説明

ips

ローカルIPをカンマ区切りで列挙した文字列

token

ユーザ識別IDをMD5でハッシュ化した16進数文字列

user

"v1.3 | <hostname> | <user>"を含む文字列

os

"linux | amd64 | pid=<pid>" を含む文字列

socket5

Socks5によるプロキシを使用する際に使用

socket5Quick

Socks5によるプロキシを使用する際に使用

inListenPor

ポートフォワードを利用する際に使用

tokenで使用されるユーザ識別IDは、Golangのxidライブラリを使用して生成されます。これはUUIDと同じくグローバルでユニークなIDとなります。


この JSON 文字列をエンコード後、 src/mode/utils.Post / src/mode/utils.SendDataByPost関数 を使い、 1秒ごとにC2にPOSTしています。

src/mode/utils.Post関数では、User-AgentをSafariに偽装してHTTP通信を行います。


応答が ERROR (hex 4552524f52) であれば 1秒スリープし、最大10回再送します。

コマンド

ZnDoorはRATとしての機能を持ち、C2サーバからコマンド実行が可能です。ビーコンを担当する関数が C2 応答を受け取り、goroutineを起動します。実際のコマンド実行に関する処理は`src/mode/process/ProcessLinux.ProcessTask`に記載されており、コマンドの実行は文字列に応じて分岐します。また、コマンド文字列の分割に、`"##"`を用いています。

ZnDoorに実装されているコマンドを以下に示します。コマンドの実行結果はシリアライズした後、ビーコンと同じ HTTP POST 通信で C2 に送信します。

コマンド

説明

shell

コマンドを実行

interactive_shell

対話型シェルを起動

explorer

ディレクトリの一覧を取得

explorer_cat

ファイルを読み込み表示

explorer_delete

ファイルを削除

explorer_upload

C2からファイルダウンロード

explorer_download

C2へファイル送信

system

システム情報を取得

change_timefile

ファイルのタイムスタンプを変更

socket_quick_startstreams

SOCKS5プロキシを開始

socket_quick_stops

システム情報を再構築してGC実行

start_in_port_forward

ポートフォワーディングを開始

stop_in_port

ポートフォワーディングを停止

socket_quick_startsreams コマンドで、SOCKS5プロキシを起動します。
ProcessTask関数においてホスト名やユーザ名、パスワード、ポートなどの情報を取り出し、socket5Quick.StartProxy関数に渡して SOCKS5やクイックプロキシを開始します。

 検知回避

ZnDoorでは、以下の検知回避機能を持ちます。

- プロセス名偽装
- タイムスタンプ変更
- 自己再実行

関数znF0q.I は自己再実行を行う関数で、/proc/self/exe を引数付きで起動し、標準入出力を継承したまま子プロセスを動かします。標準入出力を既存のファイルディスクリプタに繋ぎ、親子間で同じ標準入出力を使うことが可能になります。

関数znF0q.Hでは、プロセス名の偽装とタイムスタンプの改ざんが行われます。まず、関数`src/mode/utils.ChangeSelfTime`を呼び、さらにos.Chtimes()を呼ぶことで、自らのプロセスのタイムスタンプを変更します。タイムスタンプは固定で、必ず`2016-01-15 15:08:257450580`となります。さらに、偽装するプロセス名の候補がznF0q.MakeproceNames関数をはじめとした複数の関数で記述されています。デバッガ等でznF0q.MakeproceNames()関数を呼び出すことで、プロセス名のテーブルをデバッガ等で抽出することが可能です。

プロセスの再実行とプロセス名の偽装を繰り返すことにより、PID指定でのプロセスキルや、サンドボックス等による動的解析が困難になります。また、タイムスタンプを過去の日付にすることにより、フォレンジック調査やアンチウイルス検出を回避する目的があると考えられます。

おわりに

本稿では、React2Shell(CVE-2025-55182)を悪用したインシデント事例と、React2ShellによってデプロイされたマルウェアZnDoorについて紹介しました。React2ShellとZnDoorによる攻撃を日本国内の企業においても観測しているため、今後も引き続き注意が必要です。

付録

偽装されるプロセス名の一覧表

プロセス名

/lib/systemd/systemd --user

/sbin/audispd

/sbin/auditd -n

/sbin/multipathd -d -s

/usr/bin/abrt-dump-oops -xtD

/usr/bin/lsmd -d

/usr/bin/pulseaudio --start

/usr/bin/seapplet

/usr/lib/accountsservice/accounts-daemon

/usr/lib/policykit-1/polkitd --no-debug

/usr/lib/polkit-1/polkitd --no-debug

/usr/lib/systemd/systemd-journald

/usr/lib/udisks2/udisksd --no-debug

/usr/libexec/accounts-daemon

/usr/libexec/at-spi-bus-launcher

/usr/libexec/bluetooth/bluetoothd

/usr/libexec/caribou

/usr/libexec/colord

/usr/libexec/evolution-calendar-factory

/usr/libexec/gconfd-2

/usr/libexec/gsd-printer

/usr/libexec/gvfsd-metadata

/usr/libexec/ibus-dconf

/usr/libexec/mission-control-5

/usr/libexec/packagekitd

/usr/libexec/postfix/master -w

/usr/libexec/rtkit-daemon

/usr/libexec/tracker-extract

/usr/libexec/upowerd

/usr/sbin/abrtd -d -s

/usr/sbin/chronyd

/usr/sbin/cron -f

/usr/sbin/crond -n

/usr/sbin/cupsd -f

/usr/sbin/gdm

/usr/sbin/gssproxy -D

/usr/sbin/lvmetad -f

/usr/sbin/ModemManager

/usr/sbin/NetworkManager --no-daemon

/usr/sbin/rsyslogd -n

/usr/sbin/rsyslogd -n -iNONE

/usr/sbin/sedispatch

/usr/sbin/smartd -n -q never

/usr/sbin/sshd -D

IOC

- 通信先
    - api.qtss[.]cc
    - 45[.]76.155.14
    - 104[.]168.9.49
- 過去のZnDoorの通信先
    - 149[.]28.25.254
    - 45[.]32.126.137






関連記事 / おすすめ記事

Inquiry

お問い合わせ

お客様の業務課題に応じて、さまざまなソリューションの中から最適な組み合わせで、ご提案します。
お困りのことがございましたらお気軽にお問い合わせください。