Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
CVE-2025-55182の原理を詳細に解説!
Search
kurenaif
December 07, 2025
2
470
CVE-2025-55182の原理を詳細に解説!
kurenaif
December 07, 2025
Tweet
Share
More Decks by kurenaif
See All by kurenaif
pppp writeup
kurenaif
0
220
素数の作り方(かんたん版)
kurenaif
0
560
rustのパフォーマンス計測ってどうやるの…?
kurenaif
0
350
Featured
See All Featured
Embracing the Ebb and Flow
colly
88
4.9k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.6k
Context Engineering - Making Every Token Count
addyosmani
9
490
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
121
20k
Learning to Love Humans: Emotional Interface Design
aarron
274
41k
Reflections from 52 weeks, 52 projects
jeffersonlam
355
21k
RailsConf 2023
tenderlove
30
1.3k
Statistics for Hackers
jakevdp
799
230k
Git: the NoSQL Database
bkeepers
PRO
432
66k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
12
970
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
48
9.8k
KATA
mclloyd
PRO
32
15k
Transcript
CVE-2025-55182 ってどんな脆弱性? 今日のトピック
CVE-2025-55182 ってどんな脆弱性? ・React Server Component に任意コード実行の脆弱性 ・以下のライブラリを使っているときに影響 https://react.dev/blog/2025/12/03/critical-security-vulnerability-in-react-server-components ・Next.js で以下のバージョンを使っていて
App Router を利用している場合も影響 https://github.com/vercel/next.js/security/advisories/GHSA-9qr9-h5gf-34mp 脆弱性あり ライブラリ起因で RCE
エクスプロイトの開発状況(2025/12/06 現在) ・今現在、世の中に出ているのは、Next.js を利用したもの ・影響するかどうかは React の使い方依存と思われる https://react.dev/blog/2025/12/03/critical-security-vulnerability-in-react-server-components これ単体では影響せず? https://github.com/vercel/next.js/security/advisories/GHSA-9qr9-h5gf-34mp
Next.js で AppRouter を使っていたら 確実に RCE IUUQTHJTUHJUIVCDPNNBQMFCDGFDGDBCDGG IUUQTHJUIVCDPNNTBOGU$7& Next.js 環境で RCE するもの。React 単体では RCE は刺さらない。
React Server Components とは? ・既存の SSR (Server Side Rendering) を少し改良したもの
・今まではイベントリスナー不要のものも bundle.js に含めないといけなかった ・サーバーサイドで完結するものとそうでないものを区別して描画するための仕組み(多分) IUUQTTQFBLFSEFDLDPNNJ[ESBSFBDUTFSWFSDPNQPOFOUTOPZJXFOXPKJFLJNJOHLBTV TMJEF IUUQTKBSFBDUEFWSFGFSFODFSTDTFSWFSDPNQPOFOUT
Next.js と React Server Components IUUQTEFWMPHNFTDJVTKQSFBDUTFSWFSDPNQPOFOUTCBTJDVTBHF ・Next.js とは、 The React
Framework for the Web ・昔から SSR に強いフレームワークの印象 ・デフォルトではサーバーコンポーネントになり、 use client を使うと Client Component になる
Next.js と App Router IUUQTOFYUKTPSHEPDTQBHFT IUUQTOFYUKTPSHEPDTBQQ IUUQT[FOOEFWZBNBEBEBZPBSUJDMFTDCGEF ・従来は pages 直下に作ったものがすべてルーティングされていたが、
React Server Components の実装と同時期くらいに、app/page.tsx のみが ルーティング対象になった(App Router) ・React Server Components が新たに生まれたことで、 「サーバーコンポーネントを要求しているのか」 「クライアントコンポーネントを要求しているのか」 を区別する必要が生まれた。 (多分)
RSC Payrload / Flight protocol とは https://nextjs.org/docs/app/getting-started/server-and-client-components ・React Server Component
で利用する、React 内部で使われている Protocol ・普段は特にユーザーは気にせず使うことができる ・next.js では Next-Action というヘッダに値を入れて渡せば処理させることができる
今回の Exploit の全体像 サーバー クライアント
今回の Exploit の全体像 サーバー クライアント Next-Action: ~~~ { ヤバい Flight
Protocol} SSR 頼んだわ!
今回の Exploit の全体像 サーバー クライアント お、Next-Action に値入ってるな これは React Server
Component やな! Flight Protocol の deocde よろ~~ Next-Action: ~~~ { ヤバい Flight Protocol} { ヤバい Flight Protocol}
今回の Exploit の全体像 サーバー クライアント { ヤバい Flight Protocol} を
Decode したら ヤバいオブジェクトになったで! Next-Action: ~~~ { ヤバい Flight Protocol} { ヤバい Flight Protocol}
今回の Exploit の全体像 サーバー クライアント ヤバいオブジェクト { ヤバい Flight Protocol}
Next-Action: ~~~ { ヤバい Flight Protocol}
今回の Exploit の全体像(どこで実行しているかちょっと怪しい) サーバー クライアント ヤバいオブジェクトが どこかで await されたりする Next-Action:
~~~ { ヤバい Flight Protocol} { ヤバい Flight Protocol} ヤバいオブジェクト
今回の Exploit の全体像 サーバー クライアント ヤバいオブジェクト 帰ってきたな! 処理するで! Remote Code
Exection
step1. React Flight Protocol が React にわたるまで サーバー クライアント お、Next-Action
に値入ってるな これは React Server Component やな! Flight Protocol の deocde よろ~~ Next-Action: ~~~ { ヤバい Flight Protocol} { ヤバい Flight Protocol}
step1. React Flight Protocol が React にわたるまで 1 Next-Action: “適当な文字列”
の HTTP header がついていること 2 POST であること 3 multipart/from-data であること → decodeReplyFromBusboy という React 側の関数に渡される react から取ってくる IUUQTHJUIVCDPNWFSDFMOFYUKTCMPCCGFDCGCCDFFEDCCBGQBDLBHFTOFYUTSDTFSWFSBQQSFOEFSBDUJPOIBOEMFSUT- 入力値を渡す 関数内部で Flight が渡されていることを確認
decodeReplyFromBusboy が呼ばれるまで IUUQTHJUIVCDPNWFSDFMOFYUKTCMPCCGFDCGCCDFFEDCCBGQBDLBHFTOFYUTSDDMJFOUDPNQPOFOUTBQQSPVUFSIFBEFSTUT- IUUQTHJUIVCDPNWFSDFMOFYUKTCMPCCGFDCGCCDFFEDCCBGQBDLBHFTOFYUTSDTFSWFSMJCTFSWFSBDUJPOSFRVFTUNFUBUT- IUUQTHJUIVCDPNWFSDFMOFYUKTCMPCCGFDCGCCDFFEDCCBGQBDLBHFTOFYUTSDTFSWFSMJCTFSWFSBDUJPOSFRVFTUNFUBUT-- ・Next-Action というヘッダ ・ヘッダを取得したら String 型
・POST リクエスト → isFetchAction が True になる IUUQTHJUIVCDPNWFSDFMOFYUKTCMPCCGFDCGCCDFFEDCCBGQBDLBHFTOFYUTSDTFSWFSMJCTFSWFSBDUJPOSFRVFTUNFUBUT- ・contentType が multipart/form-data か始まっている → isMultipartAction が True になる
decodeReplyFromBusboy が呼ばれるまで isFetchAction かつ isMultipartAction の場合 decodeReplyFromBusboy が呼ばれる IUUQTHJUIVCDPNWFSDFMOFYUKTCMPCCGFDCGCCDFFEDCCBGQBDLBHFTOFYUTSDTFSWFSBQQSFOEFSBDUJPOIBOEMFSUT-
step2. React がヤバい Flight protocol を処理する サーバー クライアント { ヤバい
Flight Protocol} を Decode したら ヤバいオブジェクトになったで! Next-Action: ~~~ { ヤバい Flight Protocol} { ヤバい Flight Protocol}
RSC Payrload / Flight protocol とは(詳細版) ・かなり json に近い形式 ・$
を渡すと様々な事ができる ・例えば $1 とすると、1 番の要素を参照する ・0 から順番に処理される(多分) ・Next.js は最終的に 0 番の要素を取得し、await する IUUQTHJUIVCDPNNTBOGU$7&USFFNBJO
step1: 0 の処理 ・まずは 0 を処理する ・$1 は 1 番の要素を参照してねという意味なので、一旦保留して次に行く。
・保留する際、$1 が終わったら処理するということをメモしておく。 $1 が終わったら処理する :
step2: [0 は保留状態 ] 1 の処理 ・1 を処理する ・$2 は
2 番の要素を参照してねという意味なので、一旦保留して次に行く。 $1 が終わったら処理する :
step3: [0 は保留状態 ] [1 は保留状態 ] 2 の処理 ・2
を処理する ・特に何もないので、処理は完了する。 →$2 = {”fruitName”: ”cherry”} $1 が終わったら処理する : $2 が終わったら処理する :
step4: [0 は保留状態 ] 1 を再実行する ・保留していた $1 を実行する $1
が終わったら処理する : $2 = {”fruitName”: ”cherry”} ・ $2:fruitNameとるすると、 $2[’fruitName’]のような挙動になる → $1={”object”:”fruit”, “name”:”cherry”}
step5: 0 を再実行する → $0=[{”object”:”fruit”, “name”:”cherry”}] ・そのまま ・この値が next.js に帰っていくようなイメージ
怪しすぎる箇所 ・ここで fruitName が __proto__ だったら? ・ →普通に prototype を参照することができる
普通に prototype 参照が起こっている 様子
今回作りたい Exploit とそれを実現するための課題 課題 1: ユーザーから渡した文字列から関数オブジェクトを生成する必要がある str → Function Object
への変換が必要 課題 2: 関数オブジェクトの中に任意の文字列を入れる必要がある (このヤバい関数オブジェクトを next.js に返す) 課題 3: 関数オブジェクトを実行する必要がある(これは next.js 側) 1. 文字列型からコレを作る 2. 作った Function の中に値を入れる 3. それを実行する
Payrload の全体像 step by step で説明していきつつ、どのようにして課題を解決したのか解説する https://github.com/msanft/CVE-2025-55182/tree/main
step1: 0 の処理 ・$1 がふくまれているので保留される
step2: [0 は保留状態 ] 1 の処理 ・$1 がふくまれているので保留される ・0 番
chunk が参照される (この 0 とか 1 とかオブジェクトのことを chunk という) $@ だった場合、obj=0 になり、 getChunk(response, 0) が呼ばれ、 0 番目の chunk になる。
step3: 0 の解決 ・$1 を解決した結果、それぞれ以下のようになる chunk.__proto__.then(chunk.prototype.then) chunk.constructor.constructor (Function Object)
step4: 最終的な値 → $0=[{”then”:Function, ...}] ・帰ってきた値が thenable だった場合、その then を実行される
・どっかでこのオブジェクトに対して await かなんかしてるっぽい?
これが実行される この then() の中では、 this.status などの結果は これになる。 ・await などでは then
の要素があれば、自動的にそれを実行するようになっている ・普通にメンバ関数が実行されるので同じ階層にある諸々のパラメータは this で 参照されるようになる。 step5: chunk.then が実行されると何が起きるのか
これが実行される この then() の中では、 this.status などの結果は これになる。 ・await などでは then
の要素があれば、自動的にそれを実行するようになっている ・普通にメンバ関数が実行されるので同じ階層にある諸々のパラメータは this で 参照されるようになる。 step5: chunk.then が実行されると何が起きるのか resulved_model にして initializeModelChunk を実行し fullfilled にしてから this.value を呼ぶ
これが実行される この then() の中では、 this.status などの結果は これになる。 ・await などでは then
の要素があれば、自動的にそれを実行するようになっている ・普通にメンバ関数が実行されるので同じ階層にある諸々のパラメータは this で 参照されるようになる。 step5: chunk.then が実行されると何が起きるのか まだ this.value は JSON 文字列なので それを object にしてから resolve したい。
最後にやりたいこと ・this.value = {then: Function( 任意の文字列 )} にして、resolve を実行したい。 (resolve
は then があったら勝手に実行する ) ・initializeModelChunk で object にはできるがどうやって 関数オブジェクトにするか
・$B0 と入力すると、$@ と同じように特殊な解決をする ・resopnse は this から取ってきているため、ほとんど掌握可能 ・ Function(”好きな文字列”+”0”)という、最初目標にしていた値に! $B0
の意味
最終的に解決された結果 then が関数オブジェクトに!
None
None
None
None
None
None
None
None
None
None