一連のRSC議論について
一連のRSC/Server Functions議論について
以下の事象のどれをヨシとして、どれをヨシとしないかについてスタンスを明確にしてから議論を行う必要があります
- サーバ側で見た目をレンダリングすること (Server Componentsを用いたUIレンダリング)
- サーバ側のデータを魔法のようにクライアントに渡せてしまうこと (SCからCCへのprops受け渡し)
- クライアントがサーバの関数呼び出しを意識せず魔法のように行えてしまうこと (Server Functionsへの引数渡し)
自分は一番目は是非とも許容していきたくて(これに関してはMPAやHTML on the Wire/HotWire のメリットと同じ)、
2と3はうまく立ち回らないと自分の足を自分でぶち抜いてしまう危険な仕組みなので避け、
SPA + Backend APIと同様にAPIスキーマを定義し、意図しない値の読み書きが行われないよう
バリデーションを行うべきだという主張をしています
RSCの思想と実装の不備はしっかり分けて考える必要があります
実装の不備は今回確実に存在していたと考えます
Flightプロトコルのデシリアライズにおいて、信頼できない値を信頼していたという形で答えが出ています
一方でRSCの思想については(自分がGraphQLに親しみを持っているのもあり)
1の思想は許容したいと思っています
なお、今回脆弱性があった部分は3の部分であることに留意
いうなればRSCの脆弱性というより、Server Functionsの脆弱性
今回の脆弱性でRSCの1,2両方に言及して批判を行う声が大きいですが、
むしろRSC自体はあまり関係なく、
また思想への批判と技術的な批判を取り違えているという意味でも
すこしズレているような評判が多そうな印象を持ちます
技術的な側面でも解説をします
Flightプロトコルがユーザの入力した信頼できないデータをバリデーション無しにデシリアライズしてしまうため、以下の問題が発生し、最終的にRCEになりました
- プロパティ指定におけるプロトタイプバリデーションの不備
- プロトタイプ指定によるReact内部オブジェクトの偽造
- プロトタイプ指定によるFunctionコンストラクタの用意(evalに必要)
また別件ですが、DoS脆弱性も存在しています
- 細工したFlightプロトコルを入力させることでデシリアライザが無限ループに陥る
これは信頼できない値の入力というより、Flightプロトコルのデシリアライザのロジック不備です
これに関しても同じくバリデーションに加え、一定以上のループをストップする機構が入っています
これらの実装により、React開発チームであっても、
信頼できない値を信頼してしまうというミスをやらかすんだよ、
だからなおさら私達ユーザは信頼できない値を信頼してはいけないんだよ、よいうマインドをもち、
セキュアコーディングの観点で他山の石にすべきだな、と思います
Flightプロトコルという、万が一にでも失敗してはいけない部分で
デシリアライザの実装を失敗したことに関しては
自分も驚きの気持ちがありますが、責めすぎるのもよくないなと思い、
当事者の実装の大変さも考慮しつつ、今後設計がよくなるといいなと
前向きに捉えています
これで十分に設計がよくなるといいな・・・というお気持ちです
Flightプロトコルの実装不備について、ツイッターで過度に驚く、コード品質について疑念を持つ等のツイートを行なったことに関して、ここで謝罪いたします。すみませんでした。
余談ですが、今回の脆弱性の騒ぎに関連して
Reactの利用をやめようと主張する人はお門違いだなと思う一方、
サーバサイドTSの利用をやめよう!と主張する人については
騒ぎすぎであると同時に、あながち否定できない部分もあります
理由としては、今回のReact2Shell攻撃において、
JavaScriptの互換性を理由に継続されている仕様がいくつか狙われているからです
-
__proto__プロパティによるプロトタイプトラバーサル (チャンク偽造やFunctionコンストラクタ用意に関与)- 最小限PoCでは狙われていないことを確認したが、レポート提出時の報告者PoCには存在したことを確認している
- then プロパティが存在することを理由としたawait でのthenメソッド呼び出し (任意コード実行の発火に関与)
※ thenableのawaitの扱いについては でダックタイピングの挙動を互換性に問題がない範囲内で弱めるといった提案がなされている。stage 1なのでまだまだ先だが
これらの仕様は、JavaScriptが昔ながらのレガシーなブラウザで動作するため、
互換性を切り捨てられないため今日まで残っており、これが攻撃に使われた
このような非推奨な仕様を切り捨てられない言語をサーバサイドに利用すべきではないのでは?
という指摘は、ある程度理にかなっていると思います
とはいえ、長年活躍し親しまれる言語なら、
レガシーで攻撃に狙われる仕様というのは、少なからずどの言語にも存在します
PHPなどでもそうです
私達に出来ることは、しっかりとバリデーションを行い、
攻撃が脆弱な仕様に結びつく前にちゃんと断ち切ることだと思います