クロスサイトスクリプティング対策としてやるべき5つのこと

クロスサイトスクリプティングとは?

クロスサイトスクリプティング(略してXSS)は、WEBサイト中で動的にHTMLやJavascriptを生成している部分に、悪意のあるコードを埋め込む攻撃です。

昨年、TwitterがXSS脆弱性によって、大騒ぎになった日がありました。

こんな風に、WEBサイトに怪しげなソースコードを埋め込み、それを見た別のユーザーに悪影響を与えます。

この対策は本質的な対策法は、

悪意あるコードを埋め込めないようにする

これに尽きます。

1. <>“&は文字参照にする

HTML中に悪意あるコードを埋め込めなくするためには、特殊な意味合いをもつ<>“&の文字をエスケープする必要があります。

$str = htmlspecialchars($str, ENT_QUOTES, 'UTF-8');

こうすると、<は&lt;に、>は&gt;に、&は&amp;に、”は&quote;に、’は&#39;に変換されます。

このように文字参照に変換してしまえば、悪意あるコードを無力化できます。

第2引数は、ENT_QUOTESが一番強くエスケープしてくれるので、特に理由がなければこれを使うのが良いでしょう。

2. Javascriptに動的に文字列を渡す時はURLエンコードする

HTMLに悪意あるコードを埋め込まれるのは、まだ被害が少ないですが、Javascriptを埋め込まれると大きな被害に繋がります。

そこで可能な限りJavascriptを動的に生成することはしたくないのですが、どうしてもそうする必要が出てくる場所があります。

たとえば、Javascriptでエラーメッセージを表示させるが、そのエラーメッセージはPHPで動的に作りたい場合などです。

<?php
$error = 'エラーです。';
?>
<script type="text/javascript">
alert('<?php echo $error?>');
// alert('エラーです。');
</script>

こうしておくと、$errorに怪しげなコードが埋め込まれた時に、それがJavascriptとして実行されてしまう危険があります。(この例のように、$errorに任意の文字列が埋め込まれる心配がない場合は危険はありませんが)

function EscapeJavascriptString($s) {
    return preg_replace_callback('/[^-.0-9a-zA-Z]+/u',
    function ($matches) {
        $u16 = mb_convert_encoding($matches[0], 'UTF-16');
        return preg_replace('/[0-9a-f]{4}/', 'u$0', bin2hex($u16));
    }
    , $s);
}

そこで、このような文字列をエスケープする関数を利用します。

alert('<?php echo EscapeJavascriptString($error);?>');
// alert('u30a8u30e9u30fcu3067u3059u3002');

これで、Javascriptとして実行されるようなコードが埋め込まれても、エスケープされるので危険性がなくなります。

3. hrefやsrcの値がURLか確認する

Javascriptはscriptタグの中だけでなく、aタグのhref属性や、imgタグのsrc属性の中でも実行することができます。

<a href="javascript: alert('js!');">js</a>

だから、aタグのhref属性などにjavascriptが埋め込まれていないかを確認する必要があります。これは、1.で紹介したhtmlspecialcharsを使っても取り除けないので注意です。

function isUrl($url) {
    return (boolean)preg_match('/A(https?://|/)/',$url);
}

このような正規表現などを使って、本当にURLが指定されているかを事前に確認します。

4. php.iniでsession.cookie_httponly=on

ここからは保険的な対策です。

JavascriptからCookieにアクセスできると、XSS脆弱性によってCookieに保存されたセッションID等が漏えいする恐れがあります。

php.iniでsession.cookie_httponlyをonにしておくと、Javascript経由でCookieにアクセスすることができなくなります。cookie_httponlyの設定で不都合が生じなければ設定した方が良いでしょう。

レンタルサーバなどで直接php.iniが触れない場合は、実行時に次のようにini_setで設定することもできます。

ini_set('session.cookie_httponly',1);

5. httpd.confでTraceEnable Off

これも保険的な対策ですが、XSS対策に漏れがあった場合に、クロスサイトトレーシング(XST)という攻撃を受ける恐れがあります。

これは、HTTPのTRACEメソッドを使うことでパスワード等を盗む攻撃で、Apacheの設定でこのメソッドを使えないようにしておいた方が安全です。

参考文献

体系的に学ぶ 安全なWebアプリケーションの作り方」を参考に書きました。非常に分かりやすくて良い本です。

About katty0324

2 comments

Leave a Reply

Scroll To Top