Isomorphic JSで作られたWebサイトの脆弱性検査
西村 宗晃
サイバーセキュリティエンジニアリング部の西村です。
Recruit Engineers Advent Calendar 2016の12月6日の記事を担当します。
先日、あるWebサイトの脆弱性検査を業務で担当しました。対象のサイトは、Node.js + React + Reduxを用いてIsomorphic JSを実現しており、検査でもこのアーキテクチャに特有の脆弱性が見つかりました。
この記事では、検査で発見した脆弱性をもとに、Isomorphic JSのWebサイトを構築する際に気をつけるべきポイントを紹介します。
Isomorphic JSとは
Isomorphic JSは、近年、注目されているWebのパラダイムで、サーバとクライアントで同一のJSのソースコードを利用することが特徴です。これにより、サーバとクライアントの双方でHTMLを生成できるようになり、従来のSPAに見られたSEOの弱みを克服しつつ、高速なWebエクスペリエンスの提供が可能となります。
検査対象のサイトでは、クライアントとサーバの双方でReact + Reduxを動かすことで、この構成を実現していました。具体的には、ユーザーがサイトを訪れた際にはサーバ側で生成したHTMLを表示し、その後、ユーザーがサイト内のリンクから別のページに遷移した際は、クライアント側で生成したHTMLを表示していました。
ReactによるXSS対策の落とし穴
Webサイトでよく生じる脆弱性の1つにクロスサイトスクリプティング(XSS)というものがあります。ReactではデータをHTMLにバインドする際、XSSの保護が自動的にかかるのですが、この保護は網羅的ではありません。たとえば以下のJSXを見てみましょう。
ここで、データをHTML要素の属性値(msg.read)や要素内容(msg.title)にバインディングするときは、ReactによるXSSの保護が有効となります。しかし、ハイパーリンク属性(msg.linkURL)にURL文字列をバインドするときは、この保護が適用されません。このため、悪意のあるユーザーが「javascript:alert`1`」や「data:text/html,<script>alert`1`</script>」といった任意のスキームを持つURLを指定できる場合、XSSが生じます。
検査対象のサイトでは、お知らせのURLを表示する箇所でこの脆弱性が見つかり、アプリ側で「http:」と「https:」で始まるURL以外は指定できないように制限し、対処しました。
Reactでは、この他にも、iframe要素のsrcやsrcdoc属性、onErrorのようなイベントハンドラ属性にデータをバインディングするときにもXSSの保護がかからないので注意が必要です。
脆弱性か否か、判断の分かれるRFD (Reflected File Download)
次に紹介するのは、2014年にBlack Hat Europeというセキュリティカンファレンスで公開された「RFD (Reflected File Download)」という脆弱性です。この脆弱性は、HTTPリクエストに含まれるデータを、サーバがJSONに直接エコーバックする際に生じます。
検査対象のサイトでは、リクエストで指定した地域にある店舗を探す機能でこの脆弱性が見つかりました。この機能は「/path;areaCd=123」といったURLでアクセスでき、呼び出すと、以下のように、リクエストに含まれるデータ (123)を含むJSON を返却します。
1 |
{"selectedAreaCd":"123", "restaurants":[]} |
このパラメータに特殊な文字列を与え、Windows版Chromeブラウザで次のように呼び出します。
1 |
<a download href='https://target/path;areaCd=\"||calc||setup.bat'> Download</a> |
すると、以下のデータを含むJSONが、Windowsのバッチファイル(.bat)としてユーザーのPCにダウンロードされます。
1 |
{"selectedAreaCd":"/\"||calc||setup.bat ", "restaurants":[]} |
このバッチファイルを誤ってユーザーが開くと、JSONに含まれる「|| calc ||」という文字列がWindowsのプログラム実行箇所として評価され、以下のように計算機アプリが起動します。
RFDを脆弱性として扱うかどうかは、世界的にも判断が分かれています。たとえばGoogleは、これを脆弱性と扱わず、修正しない方針を打ち出しています。今回の件でも、これを脆弱性とするか否かを開発者と議論し、最終的に修正することとしました。
検査で見つけたOSSのFetchrモジュールの脆弱性
今回の検査では、対象のサイトが利用するFetchrというOSSのNodeモジュールにも2件の脆弱性が見つかりました。
1件目は、不正なHTTPリクエストを通じて、Nodeのサーバをダウンさせることのできるものでした。原因箇所はExpressのエラーハンドリングにも引っかからず、結果としてNodeの停止を招いていました。この脆弱性は同僚の古川さんに修正いただき、Fetchrの開発元にもフィードバックされました。
2件目は、Fetchrのサーバモジュールに任意の関数を実行させることのできるものでした。この被害はサーバ側のJSの構造によって異なりますが、検査対象のサイトでは、ある関数を実行させることでNodeを停止させることが可能でした。この脆弱性は、同僚の吉田さんにより修正いただき、開発元にもフィードバックされました。
これらの脆弱性はFetchrのv0.5.34で修正されており、npmを通じて入手が可能です。該当するバージョンのFetchrを使用している方にはアップデートをお勧めします。
さいごに
今回の脆弱性検査は、Isomorphic JSを理解する良い機会になりました。今後も社内の尖ったエンジニアの方々とコラボレーションし、エッジが効いていて、かつ安全なサービスを作ることに貢献できればと思います。
※本文中のリンクは、補足説明用に設置しています 。