JavaScript投稿を可能にすべく解決しなきゃいけないセキュリティ問題
この記事は、サイトの名前とデザインを一新した時に、最初に書くネタになると思うのですが、思い付いたので構成をメモっておきます。
掲示板やSNSなどにJavaScriptの投稿を許可すると、悪意あるコードが投稿される可能性があります。代表的なのが、XSS、iframeを使った他サイトの知らぬ間操作などですね。
この攻撃は、windowや、document、location、dom、ajaxなどを使って行われます。つまり、これらが使われているか調べれば、投稿されたJavaScriptに悪意ある攻撃が仕込まれているかわかるはずです。
ところがJavaScriptには、どんな機能を使っているか偽装する方法が用意されています。分類すると次のような感じでしょうか。
1.windowやdocumentなどを偽装する
グローバルスコープでthisを使ったり、selfプロパティを使えばできます。
2.プロパティ名を偽装する
例えば、document.cookieは、
document[ "c" + "o" + "o" + "k" + "i" + "e"]
や
const c = "cookie";
document[c]
なんて書けます。
3.文字列からコードを実行する
eval("alert(document.cookie)")なんてのは可愛いほうで、setIntervalや、数値オブジェクトのconstructorプロパティを使った方法まであります。
つまり、JavaScriptの実行内容を偽装する方法は無限にある、ということですね。
特に数値のconstructorから任意のコードが実行できる仕様を作るなんてどうかしてます。JavaScript投稿サイトなど断じて許さん、という意思を感じるほどです。
でもこれらを解決しなければ、JavaScript投稿サイトなんて作れません。偽装の方法が無限にあるのなら、実行時に判定するしかありません。
実行時とはつまり、どの機能を使って良いかを実行直前に判定する、ゲートのような仕組みを構築するということです。
ざくっと説明すると、本物のwindowやdocumentを偽物と入れ替えるAプラン、全ての処理実行時にオブジェクト、プロパティ、引数をチェックするBプランで対処します。
Bプランは理論上、JavaScriptに限らず全てのプログラムで使えるのですが、速度上不利なので、バックアッププランとして控えているだけです。実際には使うことはないと思われます。
理屈上はプランAで解決できるはずなんだけど、実装はコンパイラを作るようなものなので、簡単じゃないんですよね。
もう少しで、TreeJSやangularJSに対応できる希望的観測があるので、そこまでできたら、サイトデザインを一新して、ちゃんと公開する方向に持っていきたいなー。