Web
セキュリティ
xss

XSSに関して今一度学ぼう

More than 3 years have passed since last update.

はじめに

近年セキュリティに関してのニュースが絶えません。
技術の進化により出来る事が多くなっている事、フレームワークなどを使う事で前提知識がなくてもアプリケーションを作れるようになった事、そういう事が原因で後を絶たないのかと思います。

脆弱性コンテストとかも開催されており、かなりホットな業界ですねw
今日は有名どころの、「XSS」に関してまとめました。

オリジンとは?

「スキーム」「ホスト」「ポート」の3つの組み合わせをオリジンという。
RFC 6454 - The Web Origin Conceptで制定

クロスオリジンの場合には原則としてリソースの読み書きが禁止になることを「同一オリジンポリシー」と言います。基本的にjsが制御できるのは同一オリジンのみです。

そりゃそうですよね。同一オリジン以外でできたら、別tabで開いてたGmailのデータ抜かれてたなんて事おきちゃいますからね。

その他同一オリジンにて制約されているものの例としては

XMLHttpRequest 
Canvas
Web Storage

XMLHttpRequset Level 2 に対応しているブラウザであれば、XMLHttpRequest でクロスドメイン通信が可能になりました。

一方で同一オリジンポリシーとは別の制約を定めているのはcookieとかですかね。

XSS

クロスサイト→クロスオリジンと理解してもらえれば

攻撃者の目的

  • 不正なプログラムを拡散させる
  • cookieなどの個人情報を取る

reflected型

外部から受け取ったパラメータをWebページに表示する際に起こる脆弱

よくある例としては、検索ページや、問い合わせフォームの確認画面、マイページなど。
IEなどではXSSフィルターなどを搭載しているケースもあるし、ChromeやSafariも防止対策が行われている。とはいえFirefoxでは対策されていなかったり、100%防ぐ事はできないので、理解しておきましょう。

※xssフィルタとは
・送られてくるデータが、レスポンスにそのまま含まれている
・script実行につながる可能性があると判断される
上記の条件に該当する場合のみスクリプトを無効にする

http://hoge.com/?name="fuga"

fugaさん、こんにちは!
http://hoge.com/?name="fuga"><script>alert("脆弱性発見!")</script>

スクリプトが読み込まれてアラートが実行されれば任意のスクリプトを実行できる。
これの問題点は、他人を誘導してこのURLからアクセスさせる→cookie情報GETなんてことができるから怖い。

stored型

スクリプトが持続的に埋め込まれ、効果が永続するタイプの脆弱

これは昔2chでもありましたね。

参考)
予告.inが不正コード被害、閲覧で2ちゃんねるに犯行予告投稿

ユーザ投稿型のコンテンツをもっているサイトなどで、コンテンツにスクリプトが埋め込まれ表示される度に実行されるパターンが多いですね。

DOM型

動的にコンテンツを操作するようなスクリプトが組まれているアプリケーション上で発生する脆弱
XMLHttpRequestを使って動的にコンテンツを操作するようにかかれている正規のスクリプトのURLを変更することで、悪質なコンテンツを差し込む事ができる。

スクリーンショット 2014-12-18 11.36.19.png

ちなみにIPAのIPAテクニカルウォッチ「DOM Based XSS」に関するレポート~JavaScriptでHTMLを操作するアプリは要注意!~の画像を引用すると、
問題コードは大体独自開発によるものです。

  • 開発者が知識をつける
  • ライブラリに頼る場合は定期的なアップデートは忘れずに!

下記のようなものを使っている場合は要注意です。

location.href
location.search
location.hash
document.cookie
document.referrer
window.name

従来は同オリジンでしか通信できなかったが、現在のブラウザではXHR Level2実装により同オリジン以外でも通信できるようになった。

var url = location.href.substring( 1 );
var xhr = new XMLHttpRequest();
xhr.open( "GET", url, true );
xhr.onreadystatechange = function(){
    if( xhr.readyState == 4 && xhr.status == 200 ){
        div.innerHTML = xhr.responseText; // 取得したコンテンツを表示
    }
};
xhr.send();

例えば、
https://www.hoge.co.jp/#//hack.com/vi/hack_content
などに誘導アクセスさせるとhack.com/vi/hack_contentとアクセスをして
htmlにresponseを代入してしまいます。
非常に問題ですね。

var xhr = new XMLHttpRequest();
xhr.open( "GET", "/get_content", true );
xhr.onreadystatechange = function(){
    if( xhr.readyState == 4 && xhr.status == 200 ){
        div.innerHTML = xhr.responseText; // 取得したコンテンツを表示
    }
};
xhr.send();

当たり前ですが、urlは固定が望ましいです。
固定しないのであれば、hashでlistを作って対応するなどしてもらえれば問題ないです。

加えてIEは更にクソ仕様があります。

レスポンスヘッダーにX-Content-Type-Options: nosniffを付与しないとContent-Typeをapplication/jsonで指定していてもhttp://hoge.com/api.json/a.htmlってやるとhtmlとして開いてしまいます。

参考)
X-Content-Type-Options: nosniff つかわないやつは死ねばいいのに!

検証ツールもあるみたいなので、試してみてもいいかもしれません。

結論

結局開発者がセキュリティに関して理解しておくことが最重要です。

もう少し具体的な手段でいくと "入力の制御" & "出力の制御"をちゃんと行うという一言に尽きるのではないでしょうか。
XSSであればサニタイジングが必要です。
サニタイジングをどうやればいいんだよって人はココに詳しく載ってます。