ooooooo_qの日記

脆弱性の話とか

React.jsで起こるXSS (advent calendar 12日目の話)

[追記]この記事は情報が古めです。Reactで起こるXSSパターンは他にも存在するので、CTFやbug bountyなどの言葉と一緒に検索してみてください。


この記事は脆弱性"&'<<>\ Advent Calendar 2016の13日目の記事です。

前日の記事はnullです。

この記事を見ている皆さんは仮想DOMに魂を震わせられているでしょうか*1、それともjavascriptに疲れてきた頃でしょうか。私はimagemagick関連を調べるのに疲れてきたところです。

React.jsで起こるXSS

ここ数年のwebサービスではReact.jsのような仮想DOMを扱うライブラリを使ってhtmlがレンダリングされていることが多いので、典型的なDOM Based XSSなどは少なくなってきたように感じます*2。React.jsを例にすると、JSXがjsに変換されて仮想DOM経由でDOMを組み立てるので、テンプレートなどからHTMLの文字列組立時にエスケープ漏れになるケースが少なくなったということですね。クライアント側をReact.jsのような仮想DOM、サーバ側ではjsonだけを作る構成にするとXSSのややこしいことを考えることが減って随分と楽になります。

それでもXSSが起こるパターンが有りまして、私が把握しているのは以下の2つのケースです。(細かいことを書くとeval()new Functionとか色々ありますが)

  • リンクにjavascript:...などが指定できるケース
  • cssが自由に記述できてexpression()が出来るケース(IEのみ)

後者はIE特有の動作としてcssexpression()経由でjavascriptが呼べるものです。IEについては詳しくないので、IE11であっても互換モードなどを指定せずに動くのかは把握できていません。CSS in JSとかでユーザからの入力をstyleで扱っているケースでは問題になるかもしれません。そんなコードを作る機会もあまりなさそうですが。

advent calendar 12日目の話

http://www.adventar.org/calendars/1404#list-2016-12-12

advent calendar 12日目で書いたのは前者のjavascript schemeのパターンでした。(参考: クロスサイトスクリプティング対策 ホンキのキホン - 葉っぱ日記

f:id:ooooooo_q:20161213071333p:plain

記事のURLを入力する部分で、単にjavascript:...と入力すると保存できないのですが、後ろに//https://...とついていると保存できました。

現在は修正されていてこのパターンでは保存できません。昨日の日付が変わったあたりにadventarの作者の一人である @hokaccha さんにtwitterで報告した所、朝にはもう修正されていました*3。出力時のエスケープではなく、入力時のバリデーションによって防がれているため、すでに入力されている12日目のリンクはそのまま変わらず出力されています。

React.jsでもこういったパターンが有るのは知っていましたが、実際に刺さるのは初めてです。今回の場合はリンクのURL自体も表示されていますし、実際問題として(修正前も)あまり悪いこともできないので12日目のリンクはそのままにしています。

このXSSのパターンではユーザがクリックしないと発火しませんが、クリックジャッキングを使うかまたはステータスバーの偽装によって誘導するなどが考えられます。chromeでの例 xss *4

*1:http://qiita.com/mizchi/items/4d25bc26def1719d52e6

*2:単に使用されるjQueryのバージョンが上がったなどもあります

*3:https://twitter.com/hokaccha/status/808065021976592385

*4:昔のchromeでは改行コードで折返した最後の行がステータスバーに表示されていた