スクリプト挿入攻撃への対策メモ。
情報処理推進機構:情報セキュリティ:脆弱性対策:安全なウェブサイトの作り方はスクリプト挿入攻撃の対策が書かれている(p24, 1.5.1)。
上記の1,2に関するメモ。
php.iniのmagic_quotes_gpcがOnのとき$_GET, $_POST, $_COOKIEのパラメータに含まれるシングルクォート、ダブルクォート、バックスラッシュは自動的に\でエスケープされる。下記のコードはmagic_quotes_gpcがOffを前提としている。
getはフォームの内容をパーセントエンコードしURLの?以下にクエリ文字列として付けて送る。
クエリ文字列はkey=valueを&でつなぐ。
リクエスト http://www.example.com/index.php?key1=a&key2=b
上記リクエストのステータスライン。
GET /get.php?key1=a&key2=b HTTP/1.1
postメソッドはフォームの値をURLエンコードしてボディとしてサーバーに送る。
ボディはkey=valueを&でつなぐ。
Content-Typeはapplication/x-www-form-urlencoded。
リクエストのメソッドが予想できるときは$_REQUESTは使わずメソッドに応じて$_POST, $_GETを使う。
リクエストURL http://example.com/index.php?url=http%3A%2F%2Fexample.com
上記のgetリクエストのときは$_POSTでは値を取得できない。
<?php
$getURL = $_GET['url']; // ← http://example.com
$postURL = $_POST['url']; // 空文字
» HTTPの基礎 : HTTP | FindxFine -Web制作に関するメモ-
» パーセントエンコーディングとURLエンコード | FindxFine -Web制作に関するメモ-
HTMLを出力するときにデータを適切にエスケープしないと意図しないスクリプトを挿入される。
たとえばJavaScriptはwindow.location.hrefでリダイレクトできる。
HTMLとして出力するデータに下記スクリプトを含んでいるとhttp://www.example.comへリダイレクトされる。
<script>window.location.href="http://www.example.com";</script>
問題のあるコードを
<?php
header("Content-type: text/html; charset=UTF-8");
if (isset($_GET['url']) && $_GET['url'] !== '') {
$url = $_GET['url'];
echo <<<EOF
<html>
<head>
<title>JavaScriptでリダイレクト</title>
</head>
<body>
$url
</body>
</html>
EOF;
} else {
echo <<< FORM
<html>
<head>
<title>JavaScriptでリダイレクト</title>
</head>
<body>
<form action="get.php" method="GET">
<input type="text" name="url" size="40">
<input type="submit" value="送信">
</form>
</body>
</html>
FORM;
}
リダイレクト用のスクリプト。
<script>window.location.href="http://www.example.com";</script>
上記をパーセントエンコーディングした値をクエリ文字として追加してアクセスする(スクリプトのURLはwww.example.net/index.phpとする)。
http://www.example.net/index.php?%3cscript%3ewindow%2elocation%2ehref%3d%22http%3a%2f%2fwww%2eexample%2ecom%22%3b%3c%2fscript%3e
http://www.example.comへリダイレクトされる。
対策は出力データを適切にエスケープする。具体的には<>&”‘をhtmlspechalchars関数でHTMLエンティティへエスケープする。
<?php
header("Content-type: text/html; charset=UTF-8");
if (isset($_GET['url']) && $_GET['url'] !== '') {
$url = $_GET['url'];
$output = htmlspecialchars($url, ENT_QUOTES, 'UTF-8');
echo <<<EOF
<html>
<head>
<title>JavaScriptでリダイレクト</title>
</head>
<body>
$output
</body>
</html>
EOF;
} else {
echo <<< FORM
<html>
<head>
<title>JavaScriptでリダイレクト</title>
</head>
<body>
<form action="get.php" method="GET">
<input type="text" name="url" size="40">
<input type="submit" value="送信">
</form>
</body>
</html>
FORM;
}
htmlspecialchars関数を使うと適切にエスケープされる。
%3cscript%3ewindow%2elocation%2ehref%3d%22http%3a%2f%2fwww%2eexample%2ecom%22%3b%3c%2fscript%3e
エスケープされた出力。
<script>window.location.href="http://www.example.com";</script>
URLで使用するべきでない文字を%xx(xxは16進数)を使い符号化することをパーセントエンコーディングという。パーセントエンコーディングはURLエンコードとも言う。フォームデータをポストする際の符号化(application/x-www-form-urlencoded)もURLエンコードと言うので本記事ではURLの符号化はパーセントエンコード、フォームデータの符号化はURLエンコードと書く。パーセントエンコーディングとURLエンコードは半角スペースの処理が異なる。
» パーセントエンコーディングとURLエンコード | FindxFine -Web制作に関するメモ-
aタグのhref属性, imgのsrc属性, formのaction属性などに擬似スキームjavascript:を書くことでスクリプトを実行できる1。
<a href="javascript: alert('sample'); void(0);">Sample</a>
上記は多くのブラウザでSampleをクリックするとアラートダイアログを表示する。
擬似スキームの挿入に対してはhttp://とhttps://で始まるURLのみ許可するホワイトリストを行う。
ちなみに下記のようなコードはスクリプトを実行しない。
<a href="http://javascript: alert('sample'); void(0);">Sample</a>
» 情報処理推進機構:情報セキュリティ:脆弱性対策:安全なウェブサイトの作り方
» パーフェクトPHP (PERFECT SERIES 3)
No comments yet.
改行と段落タグは自動で挿入されます。
メールアドレスは表示されません。