前回は、
document.write/document.writeln~できるだけ使わず、代替手段を利用する
DOMのレンダリングを遅延させるなどの理由から、
たとえば、
// bad code
document.write(location.referrer);
document.
- HTML中に単純に文字列を出力したいのであれば、
前回解説したようにdocument. createTextNodeを用いてテキストノードを生成する - HTMLを生成するのであれば、
document. createElementを用いてDOM操作を行う
どうしてもdocument.
以下のコードでは、
function htmlEscape(s) {
s = s.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
return s;
}
// 変数text,urlはどちらも攻撃者がコントロール可能な文字列
var html = '<div>' + htmlEscape(text) + '<img src="' + htmlEscape(url) + '" alt="' + htmlEscape(text) + '"></div>';
document.write(html);
当然ながら、
繰り返しになりますが、
eval~現在のブラウザならJSON.parseを利用する
evalは、
もしかすると、
// bad code
var json = '{ "name" : "hasegawa", "url" : "http://utf-8.jp/" }';
var obj = eval( "(" + json + ")" );
しかし、
IE7のように、
if (window.JSON === undefined) {
var elm = document.createElement("script");
elm.setAttribute("type", "text/javascript");
elm.setAttribute("src", "json2.js");
document.body.appendChild(elm);
}
/* ... */
var json = '{ "name" : "hasegawa", "url" : "http://utf-8.jp/" }';
var obj = JSON.parse(json );
そもそも、
// 変数textは攻撃者がコントロール可能な文字列
function foo (text) {
var codes = {
"alert" : "alert('Hello from alert');",
"prompt" : "prompt('Enter the tex')",
"confirm" : "confirm('Choose ok or cancel');"
};
if (codes[text] !== undefined) {
eval(codes[text]); // evalには攻撃者がコントロール可能な文字列は渡らない
}
}
setTimeout/setInterval~引数では文字列ではなく関数を渡すようにする
setTimeoutやsetIntervalは、
// bad code
// 変数 text は攻撃者がコントロール可能な文字列
setTimeout("alert('" + text + "');", 1000);
そのため、
// 変数tex は攻撃者がコントロール可能な文字列
setTimeout(function( s ){ alert( s ); }, 1000, text);
なお、
// 変数textは攻撃者がコントロール可能な文字列
setTimeout(
(function (s){
return function(){ alert(s); };
})(text), 1000
);
Function~引数にコントロール可能な文字列が渡らないようにする
Functionコンストラクタを使用すると、
// bad code
// 変数textは攻撃者がコントロール可能な文字列
var func = new Function("alert('" + text + "'); return 0;");
func();
そもそも、
jQuery()/$()/$.html()~自分で書くときより挙動が見えにくくなるのでいっそう注意を
jQueryは、
jQueryのAPIでシンクとして働く代表的な機能としては、
// bad code
// 変数textは攻撃者がコントロール可能な文字列
$("#element").html(text); // 通常のinnerHTMLと同様に任意のHTMLが生成される
$(text).append("<div>news</div>"); // textに「<img src=# onerror='alert(1)'>」などが設定されるとスクリプトとして実行される
jQueryを使う場合にDOM-based XSSを避けるには、
- $.html()ではなく、
$.text()を使う - $()へ渡すセレクタは、
攻撃者がコントロールできないようにする
jQueryに限った話ではありませんが、
今回は、
次回は、