クロスサイト・スクリプティング(XSS)その3
JavaScriptの動的生成
最近のWebアプリケーションではJavaScriptの一部をサーバ側で動的に生成する例が多く見られるようになった。典型的なのはJavaScriptの文字列リテラルを生成する場合である。
イベントハンドラのXSS
次のスクリプトはonloadイベントで呼び出される関数の引数を生成している。
<head><script> function init (a) { /* 処理 */ } </script></head> <body onload="init('<?php echo htmlspecialchars($_GET['name'], ENT_QUOTES) ?>'"> </body>
htmlspecialchars()でエスケープしているので問題ないように思えるが、実際にはXSS脆弱性がある。
「name=');alert(document.cookie)//」
というクエリストリングを指定してスクリプトを実行すると、HTMLは以下のようになる。
<body onload="init('');alert(document.cookie)//')">
属性値は文字参照が解釈されるので、以下のJavaScriptが実行される。
#クエリストリングの末尾のスラッシュ2つは余計な"')"をコメントアウトしている。
init('');alert(document.cookie)//')
脆弱性の原因はJavaScriptの文字列リテラレルのエスケープがされていなかったことである。そのため、入力パラメータ中のシングルクウォートがデータとしての文字ではなくJavaScriptの文字列終端に使われ、alert()の挿入を許す結果となった。
対策は後述。
JavaScriptの文字列リテラルのエスケープとして最低限必要な文字列は下表。
文字 | エスケープ後 |
---|---|
\ | \\ |
' | \' |
" | \" |
改行 | \n |
script要素のXSS
script要素内でJavaScriptの一部を動的に生成する場合、script要素内ではタグや文字列参照を解釈しないのでHTMLエスケープは不要で、JavaScript文字列リテラルのエスケープを行う。しかし、それだけでは脆弱性が残る。
以下のスクリプトは脆弱性がある。
<script> $('#name').text('<?php echo escape_js($_GET['name']); ?>'); </script>
escape_js()はJavaScript文字列リテラルをエスケープする関数とする。
「</script><script>alert(document.cookie)//」
というクエリストリングを指定してスクリプトを実行すると、script要素は以下のようになる。
<script> $('#name').text('</script><script>alert(document.cookie)//'); </sciprt>
"</script>"でscript要素が一旦終端して、次の"<script>"で始まるscript要素でalert()が実行される。
JavaScriptの文字列リテラルの動的生成の対策
- JavaScriptの文字列リテラルとしてエスケープする。
- イベントハンドラ中の場合は1の結果をHTMLエスケープする
- スクリプト要素内の場合は1の結果に"</"という文字列が出現しないようにする。
JavaScriptのエスケープルールは複雑なため対処漏れが生じやすく、基本的にJavaScriptの動的生成は避けるべきである。
しかし、やむを得なず行う場合の対策として以下の2つがある。
- Unicodeエスケープ
英数字以外をすべてをエスケープする。UnicodeコードポイントU+XXXXの文字を\uXXXXで表す。
実際には英数字以外にもマイナスとピリオドもエスケープしなくてセキュリティ上は問題ない。 - script要素の外部でパラメータ定義してJavaScriptから参照する方法
type属性がhiddeのinput要素などの値を動的に生成して、それをJavaScriptから参照する。
この方法であればJavaScriptの動的生成をせずに済む。
参考文献:体系的に学ぶWebアプリケーションの作り方 4.3.2 クロスサイトスクリプティング(発展編)
![]() | 体系的に学ぶ 安全なWebアプリケーションの作り方 脆弱性が生まれる原理と対策の実践 徳丸 浩 ソフトバンククリエイティブ 2011-03-03 売り上げランキング : 4070 Amazonで詳しく見る by G-Tools |
« クロスサイト・スクリプティング(XSS)その2 | Main | クロスサイト・スクリプティング(XSS)その4 »
「プログラミング、技術情報」カテゴリの記事
- PHPStorm 2018.1.7 に更新(2018.12.09)
- 技術メモをQiitaに移行(2016.01.24)
- 正規表現メモ:ものぐさ(最小)マッチング(2015.11.29)
- BASE64にエンコード/デコードするバッチファイル(2015.11.23)
- Windows7の検索ボックスの検索条件指定(フォルダの除外など)(2015.08.16)
「PHP」カテゴリの記事
- PHPStorm 2018.1.7 に更新(2018.12.09)
- PHPメモ051:includeとrequireの使い分け(2015.06.19)
- CakePHPのインストール(2015.06.14)
- PHPからPDOでPostgreSQLに接続する(2015.06.09)
- PHPでメールを送信したら一部のOutlookで受信したメールでヘッダがおかしくなった(2015.05.31)
「セキュリティ」カテゴリの記事
- PHPメモ041:パスワードのSalt付きハッシュ値(2014.08.09)
- ファイルインクルード脆弱性(2014.05.18)
- ファイルダウンロードによるXSS その3(2014.03.27)
- ファイルダウンロードによるXSS その2(2014.03.23)
- ファイルダウンロードによるXSS その1(2014.02.24)
The comments to this entry are closed.
« クロスサイト・スクリプティング(XSS)その2 | Main | クロスサイト・スクリプティング(XSS)その4 »
Comments