Cosnomi
Cosnomi

医療×IT / 医学生 / Web(React, Flask) / 機械学習(画像認識, Keras)

Twitter / GitHub / Keybase

XSSについて改めて調べてみた

XSS というのは誰もが耳にしたことがある有名な攻撃手法だと思いますが、恥ずかしながらその具体的な手法や対策について私はあまり知りませんでしたので、今回調べてまとめてみました。

概要

XSS(cross site scripting)は、他の Web サイトへ悪意あるスクリプトを埋め込むことによってそのサイトの権限でスクリプトを実行する攻撃です。

通常、クロスオリジンでのデータ取得は SOP によって制限されていますが、同一オリジンからのアクセスに偽装することでその制限を回避できるのです。(実際には偽装とはいえないかもしれません。そのデータは確かに同一オリジンから送信されているのですからブラウザ側ではどうしようもありません)

インジェクションの方法

では、どのようにして他のサイトへスクリプトを埋め込むのでしょうか。

要するに、与えた文字列が相手のサーバーからそのまま帰ってくるようにすればいいわけですから、最も典型的なのはフォームへのインジェクションでしょう。

例えば、hogehoge と入力して送信すると、タグをrenderして「hogehoge でよろしいですか?」と表示する Web サイトは XSS 脆弱性があります。もちろん、このような危険のないタグに限定してrenderしているのなら問題ありませんが、そうでない場合、hogehoge にスクリプトを埋め込めば、レスポンスにはそのスクリプトが含まれてしまい、同一オリジンとして実行されてしまうからです。

しかしながら、通常、フォームに自分で攻撃用のスクリプトを入れることなんてありませんから、あまり問題ないように感じられます。しかし、それを GET パラメータなどに含めたらどうでしょうか。検索結果のページなどではしばしばフォームの入力内容を GET パラメータに含めますので、適切なエスケープがされていなければ、そこに悪意のあるスクリプトを埋め込むことも可能です。URL 短縮サービスなどを利用すればよりわかりにくくすることが出来るでしょう。

以上の攻撃手法はユーザの入力を反射しているので特に反射型 XSS (Reflected XSS)とも呼ばれます。

単純なフォームではなく掲示板のような場合はより深刻です。悪意のあるスクリプトが書き込まれれば、永続的にそのサイトに埋め込まれてしまい、訪問者全員に影響が出てしまうからです。(反射型なら悪意のあるURLを踏んだユーザーにしか影響が出ないのに対し、こちらは正規のURLに訪問したユーザーにも影響が出る)

これはStored XSS または Persistent XSSと呼ばれます。

何が出来るのか

SOP(同一生成元ポリシー)を無視できるということです。これがどれだけ危険かは明らかです。具体的には

  • ページ改ざん(DOM を使えばいいです)
  • セッション奪取(cookie を読めばいいです)
  • そのページのデータを取得(XHR を使えばいいです)

などなど多岐にわたります。

一方、フロントエンドの JavaScript なので以下のようなことはできません。

  • クライアント PC に保存されているファイルを盗む
  • 全く別の Web サイト(非攻撃対象)のデータを盗む
  • クライアント PC を破壊する(ブラクラなどは別として)

対策

最も重要なのはスクリプトに使われるような文字をescape (sanitize) することです。Web の世界におけるエスケープは、「\」ではなく「&」を使って別な文字列に置き換えます。

具体的に、XSS を防ぐためには以下の文字をエスケープするべきです。

「<」「>」「”」「’」「&」

前者 2 つはタグを阻止するためですね。次の 2 つは属性値に出力する際の対策です。最後の&は直接 XSS には関わってきませんが、置き換えてあげないとユーザの入力した「&」が表示されなくなるので必要です。(C 言語などで「\\」を表示するには「\\\\」としなければならないのと同じです)

まとめ

  • XSS は標的のサイトの中にスクリプトを埋め込むので、SOP の制限を受けない
  • 対策としてはタグに関連する文字のエスケープが有効
  • ユーザーからの入力は信頼しないこと

コメントフォームは設置していませんので、ご意見・ご感想などはTwitter(@cosnomi)などへお願いします。