前回および前々回で,
一部のタグを許容してHTMLを組み立てる3つの場面
JavaScriptを使用して複雑なHTMLの操作を行うようなWebアプリケーションにおいては,
- サーバ側でHTML断片となる文字列を生成し,
ブラウザ上でHTML内に流し込む - あらかじめ定まった構造のHTMLをJavaScriptにて生成し,
その一部にデータを当てはめる - ユーザーからの入力に基づき,
自由にHTMLを生成する
それぞれの状況について,
サーバ側でHTML断片となる文字列を生成し, ブラウザ上でHTML内に流し込む
「XMLHttpRequestを用いて,
var xhr = new XMLHttpRequest();
var url = "/news-update";
xhr.open("GET", url, true);
xhr.onload = function () {
// サーバ上では「<div><a href="/news/20150101/">新製品のお知らせ</a></div>」のような文字列を返す
document.getElementById("content").innerHTML = xhr.responseText;
};
xhr.send(null);
このような場合,
- サーバ上で生成されるHTML断片文字列にXSSが存在する
- XMLHttpRequestの接続先が攻撃者によってコントロール可能
ブラウザ上のJavaScriptでは,
また,
たとえば次のコードは,
// bad code
// URL内の#より後ろの部分をXMLHttpRequestの接続先として使用
// http://example.jp/#/newsであれば/newsをXMLHttpRequestで取得する
// 攻撃者はhttp://example.jp/#//attacker.example.com/のようなURLへ誘導することでXSSが発生する
var url = location.hash.substring(1);
var xhr = new XMLHttpRequest();
xhr.open("GET", url, true); // XMLHttpRequestの接続先はhttp://attacker.example.com/となる
xhr.onload = function () {
document.getElementById("content").innerHTML = xhr.responseText;
};
xhr.send(null);
この対策として,
// URL内の#より後ろの部分でXMLHttpRequestの接続先を識別
// http://example.jp/#newsであれば/newsを,http://example.jp/#updateであれば/updateをXMLHttpRequestで取得する
// 接続先候補としては/news,/update,/infoがあるとする
var pages = {
news : "/news",
update : "/update",
info : "/info"
};
var target = location.hash.substring(1);
var url = pages[target];
if (url === undefined || !pages.hasOwnProperty(target) ) {
return; // リストに存在しない場合は関数を抜ける
}
var xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.onload = function(){
document.getElementById("content").innerHTML = xhr.responseText;
};
xhr.send(null);
XMLHttpRequestを使用する際のセキュリティ上の注意点については,