エスケープする文字

何処とはいいませんけど、あるサイトの脆弱性が非常に気になる今日この頃。そのサイトはPHPを使っていて、いろんなところにフォーム*1がある。そして、ほとんどすべてのフォームでいわゆる「サニタイジング」を行っていない(!)
文字数制限が入っている部分もあって、さすがに全角10文字だと何もできない*2けど、文字数制限なしの部分も数ヶ所発見・・・
で、これはやばいと思ってちょっと前から管理者に問い合わせてるんだけど、全く音沙汰なしときた。さて、このサイトが攻撃されなきゃいいけど・・・


で、話はエスケープする文字についてなんだけど、このサイトを作った人は、文字列だけをエスケープすればいいと思ってるようで、シングルコーテーションとダブルコーテーションだけはエスケープしていた。
なぜそう思ったのかはおそらく、「いくらJavaScript等が使えたって、文字列が使えないんじゃぁ攻撃用のスクリプトなんてかけないだろう。」と、こんな感じじゃなかろうか?
まぁ確かに、どこか別のページに飛ばすにしたって、リンク先の文字列が必要なわけで、その文字列が使えないんじゃぁまともなスクリプトは書けそうにない・・・って、ほんとか!?


もちろんそんなことはない。JavaScript文字コードから文字列を得るメソッド*3が存在する。
これを使えば、文字コードさえわかれば任意の文字列をプログラム中に埋め込むことができる。
たとえばこんな風にやるわけだ。

alert(String.fromCharCode(33030, 24369, 24615));

実行してみる
これで「脆弱性」と書かれたアラートが出たはずだ。このスクリプトには文字列は出てこない。


さて、でも文字コードなんて調べるのが面倒だ、というかもしれない。まぁ、いちいち調べるのはさすがに骨が折れるので、これも簡単なスクリプトを作ってしまう(あれ?攻撃側に傾いてる?)。

function convert(form) {
    var result = "";
    result += "String.fromCharCode(";
    var str = form.origin.value;
    for (var i = 0; i < str.length; i++) {
        result += str.charCodeAt(i);
        if (i != str.length-1) result += ",";
    }
    result += ")";
    document.getElementById("result").innerText = result;
}

これをちょこちょこっとHTML*4に埋め込んだのが下のリンク先。
実行してみる
これで任意の文字列をスクリプト内に埋め込める!って・・・あれれ?
まぁこんな感じに、ダブルコーテーションやシングルコーテーションだけをエスケープしたところで、JavaScriptの前にはあまり意味はないことが分かって頂けたと思う。scriptタグ等の使用を禁止するなり、<や>等をエスケープするなり、きちんと対策をとらないといけない。もちろん、これらはクライアントサイドで防ぐのではなく、サーバサイドで防がなければ意味はないが・・・まぁ、この理由は分かるでしょう*5


ちなみにこれらのスクリプトを使用したことによる被害等の責任は取りませんよ、もちろん。

*1:HTMLのform。そのサイトはHTML的にも滅茶苦茶で、もう目も当てられない。

*2:直接フォームに記述するのが不可能なだけであって、他のやり方で突破できる・・・

*3:fromCharCodeメソッド

*4:すみません。目も当てられないHTMLです。実行できるかどうかはブラウザ次第・・・

*5:そのクライアントを使う必要は別にない。自分でクライアント作って、それを使ったら・・・で、上で言った文字制限はクライアントサイドでやっていたので・・・