Jetzt, da alle gängigen Browser Sandbox-Iframes unterstützen, gibt es einen viel einfacheren Weg, den ich für sicher halte . Ich würde es lieben, wenn diese Antwort von Personen überprüft werden könnte, die mit dieser Art von Sicherheitsproblemen besser vertraut sind.
HINWEIS: Diese Methode funktioniert in IE 9 und früheren Versionen definitiv nicht. In dieser Tabelle finden Sie Browserversionen, die Sandboxing unterstützen. (Hinweis: Die Tabelle scheint zu sagen, dass es in Opera Mini nicht funktioniert, aber ich habe es gerade ausprobiert und es hat funktioniert.)
Die Idee ist, einen versteckten Iframe mit deaktiviertem JavaScript zu erstellen, Ihren nicht vertrauenswürdigen HTML-Code einzufügen und ihn analysieren zu lassen. Anschließend können Sie den DOM-Baum durchsuchen und die Tags und Attribute kopieren, die als sicher gelten.
Die hier gezeigten Whitelists sind nur Beispiele. Was am besten zur Whitelist gehört, hängt von der Anwendung ab. Wenn Sie eine komplexere Richtlinie benötigen als nur Whitelists mit Tags und Attributen, kann diese Methode berücksichtigt werden, nicht jedoch dieser Beispielcode.
var tagWhitelist_ = {
'A': true,
'B': true,
'BODY': true,
'BR': true,
'DIV': true,
'EM': true,
'HR': true,
'I': true,
'IMG': true,
'P': true,
'SPAN': true,
'STRONG': true
};
var attributeWhitelist_ = {
'href': true,
'src': true
};
function sanitizeHtml(input) {
var iframe = document.createElement('iframe');
if (iframe['sandbox'] === undefined) {
alert('Your browser does not support sandboxed iframes. Please upgrade to a modern browser.');
return '';
}
iframe['sandbox'] = 'allow-same-origin';
iframe.style.display = 'none';
document.body.appendChild(iframe);
iframe.contentDocument.body.innerHTML = input;
function makeSanitizedCopy(node) {
if (node.nodeType == Node.TEXT_NODE) {
var newNode = node.cloneNode(true);
} else if (node.nodeType == Node.ELEMENT_NODE && tagWhitelist_[node.tagName]) {
newNode = iframe.contentDocument.createElement(node.tagName);
for (var i = 0; i < node.attributes.length; i++) {
var attr = node.attributes[i];
if (attributeWhitelist_[attr.name]) {
newNode.setAttribute(attr.name, attr.value);
}
}
for (i = 0; i < node.childNodes.length; i++) {
var subCopy = makeSanitizedCopy(node.childNodes[i]);
newNode.appendChild(subCopy, false);
}
} else {
newNode = document.createDocumentFragment();
}
return newNode;
};
var resultElement = makeSanitizedCopy(iframe.contentDocument.body);
document.body.removeChild(iframe);
return resultElement.innerHTML;
};
Sie können es hier ausprobieren .
Beachten Sie, dass ich in diesem Beispiel Stilattribute und Tags nicht zulasse. Wenn Sie dies zulassen, möchten Sie wahrscheinlich das CSS analysieren und sicherstellen, dass es für Ihre Zwecke sicher ist.
Ich habe dies in mehreren modernen Browsern (Chrome 40, Firefox 36 Beta, IE 11, Chrome für Android) und in einem alten Browser (IE 8) getestet, um sicherzustellen, dass es vor dem Ausführen von Skripten auf Kaution funktioniert. Es würde mich interessieren, ob es Browser gibt, die Probleme damit haben, oder Randfälle, die ich übersehen habe.