DOM に配置する前に、タグ、属性、および値のホワイト リストを使用して HTML 文字列をサニタイズしたいと考えています。ドキュメントに dom 要素を追加するまで悪意のある JavaScript が実行されないと仮定して、安全に dom 要素を構築し、それをトラバースしてホワイト リスト フィルタを実装できますか? このアプローチに落とし穴はありますか?
3 に答える
@rvighneの回答によると、ドキュメントに挿入するまで何も実行されないように見えますが、少なくともこれらの(異常な)例外があります(FF 27.0でテスト済み):
var userInput = '<a href="http://example.com" onclick="alert(\'boo!\')">Link<\/a>';
var el = document.createElement('div');
el.innerHTML = userInput;
el.addEventListener("click", function(e) {
if (e.target.nodeName.toLowerCase() === 'a') {
alert("I will also cause side effects; I shouldn't run on the wrong link!");
}
});
el.getElementsByTagName('a')[0].click(); // Alerts "boo!" and "I will also cause side effects; I shouldn't run on the wrong link!"
...また...
var userInput = '<a href="http://example.com" onclick="alert(\'boo!\')">Link<\/a>';
var el = document.createElement('div');
el.innerHTML = userInput;
el.addEventListener("cat", function(e) { this.getElementsByTagName('a')[0].click(); });
var event = new CustomEvent("cat", {"detail":{}});
el.dispatchEvent(event); // Alerts "boo!"
...または... ( setUserData は非推奨ですが、まだ機能しています):
var userInput = '<a href="http://example.com" onclick="alert(\'boo!\')">Link<\/a>';
var span = document.createElement('span');
span.innerHTML = userInput;
span.setUserData('key', 10, {handle: function (n1, n2, n3, src) {
src.getElementsByTagName('a')[0].click();
}});
var div = document.createElement('div');
div.appendChild(span);
span.cloneNode(); // Alerts "Boo!"
var imprt = document.importNode(span, true); // Alerts "Boo!"
var adopt = document.adoptNode(span, true); // Alerts "Boo!"
...または反復中...
var userInput = '<a href="http://example.com" onclick="alert(\'Boo!\');">Link</a>';
var span = document.createElement('span');
span.innerHTML = userInput;
var treeWalker = document.createTreeWalker(
span,
NodeFilter.SHOW_ELEMENT,
{ acceptNode: function(node) { node.click(); } },
false
);
var nodeList = [];
while(treeWalker.nextNode()) nodeList.push(treeWalker.currentNode); // Alerts 'Boo!'
しかし、この種の (異常な) イベントの相互作用がなければ、DOM に組み込むという事実だけでは、私が検出できる限り、副作用を引き起こすことはありません (もちろん、上記の例は工夫されたものであり、そうではありません)あったとしても、非常に頻繁に遭遇することを期待してください!)。
HTML に埋め込まれたスクリプトは、ドキュメントに挿入されるまで実行できません。任意のページで次のコードを実行してみてください。
var html = "<script>document.body.innerHTML = '';</script>";
var div = document.createElement('div');
div.innerHTML = html;
何も変わらないことに気付くでしょう。HTML 内の「悪意のある」スクリプトが実行された場合、ドキュメントは消失しているはずです。したがって、DOM を使用して HTML をサニタイズすることができ、HTML に悪い JS が含まれていることを心配する必要はありません。もちろん、サニタイザーでスクリプトを切り取る限り。
ちなみに、あなたのアプローチは、ほとんどの人が試みるよりもかなり安全でスマートです(正規表現で解析してください、かわいそうな愚か者)。ただし、これについては、 HTML Purifierなどの、優れた信頼できる HTML サニタイズ ライブラリに依存することをお勧めします。または、クライアント側で実行する場合は、ESAPI-JSを使用できます(@Brett Zamir が推奨)