クロスサイトスクリプティングとは?
状態:-
閲覧数:2,566
投稿日:2014-05-15
更新日:2018-04-26
表記
英語
・cross site scripting
略称
・XSS
※「CSS」ではなく「XSS」と表記される理由は、同分野でよく使用される「Cascading Style Sheets」の略語と同じになることを避けたため
ユーザのブラウザ上で悪意のあるスクリプトを実行させるセキュリティ攻撃
Webアプリケーションの脆弱性を利用した攻撃
・「悪意あるコードを埋め込まれたWebサイト」を訪れたユーザが、ユーザ自身の利用ブラウザ上で、意図せず不正なスクリプトを実行させられてしまうこと
(別のサイトに仕組まれた悪意のあるコードを、利用者自身のブラウザで実行してしまうこと)
・Webサイトの利用者が入力した内容をそのまま画面に出力するプログラムには、この脆弱性が存在する
攻撃対象は?
・「スクリプト埋込可能な脆弱性」があるWebサイト
・出力処理に問題があるWebサイト
攻撃内容
・Webサイト内で動的にHTMLやJavascriptを生成している部分に、悪意のあるコードを埋め込む
Webサイト攻撃の結果、実際に悪影響を被る対象は?
・そのWebサイトのページを閲覧しているユーザ
・具体的には、標的となったサイトで任意のJavaScriptを実行させられてしまうことが問題となる
・Webサイト自体は、直接の悪影響を被らない
攻撃と被害の流れ / クロスサイトスクリプティング処理を実行するタイミング / 対策は3種類
攻撃と被害の流れ
1.攻撃
・XSSの脆弱性があるページに、悪い人がスクリプト(多くの場合Javascript)を埋め込む
2.被害
・そのページを開いたユーザが攻撃を受けてしまう
クロスサイトスクリプティング処理を実行するタイミング
入力で処理しても良い?
・エスケープ処理のタイミングは入力データのチェック時ではなく、HTMLの生成時(出力時)に行うべき
・いろんな入力源から入り込んでくるデータを漏れなくエスケープ処理できるから
小さなプログラム
・どちらでも良い
・数行程度のプログラムなら、入力直後で処理するのも、HTML出力の直前で処理するのも同じこと
大規模プログラム
・入力から出力までのデータフローは長くて複雑なパス(道のり)を構成
・真ん中あたりで処理するのは最悪
・処理されているかいないかの確認が難しくなるから
・入力直後か出力直前
入力直後のエスケープ処理が良くない理由
・入力時点では値の目的が不明
・「<」を「<」に変換する必要があるのは、その値がHTML出力で使われるという理由から
・その入力値が、もしSQL文の一部として使われるならば、SQLインジェクション対策をしなくてはならない。具体的には「'」の文字を処理
・SQL文にも使われるしHTML出力にも使われるなら、両方処理する必要がある
・入力直後でサニタイズすると、両方処置した値がHTML出力に使われたとき、無駄に「'」がエスケープされて「''」とか「\'」と表示されてしまうという、マヌケなことが起きる
・「外部からの入力に依存していない値については(セキュリティ上問題ないので)エスケープを省略する」という発想は、利益がない(いまどきそんな省略で性能に変化が出ることはない)ばかりか、メンテナンス性を悪くし、脆弱性の原因となります。
・クロスサイトスクリプティング脆弱性を排除するには、HTML文字列を書き出す部分で、「<」などを「<」などに変換(エスケープ処理)すればよい
対策は3種類
1.HTMLエスケープ
2.URL属性部分の対応
3.イベントハンドラ属性の対応
クロスサイト・スクリプティングの脆弱性を有するコード例
脆弱性コード例
予め、$_GET["name"]に不正なJavaScriptを格納させておく
<?php
$_GET["name"] ='<script language="JavaScript">alert("危険な処理")</script>';
?>[
エスケープせずに、そのまま画面出力すると、任意のJavaScriptが実行されてしまう
<?php
$name = $_GET["name"];
print("ようこそ、{$name}さん!");
?>
対策を施したコード例
クロスサイト・スクリプティング対策を施したコード例
・$_GET["name"]に不正なJavaScriptを格納
<?php
$_GET["name"] ='<script language="JavaScript">alert("危険な処理")</script>';
?>
対策1.htmlspecialchars()関数を使って,<,>,",',&をHTMLエスケープ
// もしくは,htmlspecialchars()関数を使って,<,>,",',&をHTMLエスケープする
$name = htmlspecialchars($_GET["name"]);
print("ようこそ、{$name}さん!"); //ようこそ、<script language="JavaScript">alert("危険な処理")</script>さん!
対策2.str_replace()関数を使って,<と>を削除
// str_replace()関数を使って,<と>を削除する
$name = str_replace(array("<", ">"), "", $_GET["name"]);
print("ようこそ、{$name}さん!"); //ようこそ、script language="JavaScript"alert("危険な処理")/scriptさん!
対策3.strip_tags()関数を使ってタグを取り除く
// もしくは,strip_tags()関数を使ってタグを取り除く
$name = strip_tags($_GET["name"]);
print("ようこそ、{$name}さん!"); //ようこそ、alert("危険な処理")さん!
HTMLエスケープを行う関数
主に3種類
1 htmlspecialchars
・「<」「> 」をそれぞれ「&lt;」「&gt;」へ置換
・ 変換に使用されるエンコーディング指定を省略した場合のデフォルト値は、PHP 5.4.0 以前のバージョンでは ISO-8859-1 なので、注意が必要
$hoge=htmlspecialchars($_GET["hoge"],ENT_QUOTES,'UTF-8');
2 str_replace
・「<」と「>」を削除
3 strip_tags
・「<」から「>」で囲まれた範囲を削除
XSS脆弱性対策(1) - エスケープ処理
エスケープ処理とは?
・スクリプトとして意味を持つ文字を無効化する
具体的な対応
htmlspecialchars関数でエスケープ処理
& → &
< → <
> → >
" → "
' → '
XSS脆弱性対策(2) - URL属性部分の対応
URL属性とは?
・aタグのhref属性やimgタグのsrc属性など、URL指定するタグ属性のこと
<a href="★★">テスト</a>
・URL属性部分に入力データを埋め込む場合、単純な置換処理では対応不可
・エスケープ処理をしてもスクリプトを埋め込まれ実行される可能性がある
htmlspecialchars()関数でエスケープ処理しても、Javascriptが実行されてしまう例
<?php
$input = 'javascript:alert(\'clicked!\');' // ユーザからの入力値(本来は$_POSTなどで受ける)
?>
<a href="<?php echo htmlentities($input,ENT_QUOTES); ?>">click</a><br>
<a href="<?php echo htmlspecialchars($input,ENT_QUOTES,'UTF-8'); ?>">click</a>
対策
・許可するスキームを(https, http, mailto)などを定義し、それと一致するかどうかでチェック実施
・最も良い対策は、URL属性にあたるところを、ユーザーからの入力に依存するような作りにしないこと
XSS脆弱性対策(3) - その他の注意すべき点 / イベントハンドラ属性
イベントハンドラ属性
・onmouseover
・onchange
・onload
・onfocusなど
<span onmouseover="★★');">テスト</span>
何が問題?
・エスケープ処理をしてもスクリプトを埋め込まれ実行される可能性がある
対策
・埋め込みたいスクリプト関数名のリストを予め用意しておき、入力データに対応するスクリプト関数名を埋め込む
・入力データをそのままイベントハンドラ属性部分に埋め込んではいけない
script タグ
script タグで囲まれている部分
<SCRIPT src="★★"></SCRIPT>
style 属性
<br style=left:★★>
<style type="text/javascript">★★</style>
<style type="text/javascript">★★</style>
外部スタイルシートへのリンク
<link rel="stylesheet" href="★★">