aem*_*kei 72 html javascript security html-sanitizing
我需要显示通过跨域请求加载的外部资源,并确保只显示" 安全 "内容.
可以使用Prototype的String#stripScripts删除脚本块.但处理程序如onclick或onerror仍在那里.
是否有任何图书馆至少可以
embed或object).那里有任何与JavaScript相关的链接和示例吗?
Mik*_*uel 105
2016年更新:现在有一个基于Caja清洁剂的Google Closure软件包.
它有一个更干净的API,被重写以考虑现代浏览器上可用的API,并与Closure Compiler更好地交互.
无耻的插件:请参阅caja/plugin/html-sanitizer.js以获取经过全面审核的客户端html清理程序.
它是白名单,不是黑名单,但白名单可根据CajaWhitelists进行配置
如果要删除所有标记,请执行以下操作:
var tagBody = '(?:[^"\'>]|"[^"]*"|\'[^\']*\')*';
var tagOrComment = new RegExp(
'<(?:'
// Comment body.
+ '!--(?:(?:-*[^->])*--+|-?)'
// Special "raw text" elements whose content should be elided.
+ '|script\\b' + tagBody + '>[\\s\\S]*?</script\\s*'
+ '|style\\b' + tagBody + '>[\\s\\S]*?</style\\s*'
// Regular name
+ '|/?[a-z]'
+ tagBody
+ ')>',
'gi');
function removeTags(html) {
var oldHtml;
do {
oldHtml = html;
html = html.replace(tagOrComment, '');
} while (html !== oldHtml);
return html.replace(/</g, '<');
}
Run Code Online (Sandbox Code Playgroud)
人们会告诉你,你可以创建一个元素,然后分配innerHTML然后获取innerTextor textContent,然后转义实体.不要那样做.它易受XSS注入攻击,因为即使节点从未附加到DOM,<img src=bogus onerror=alert(1337)>也会运行onerror处理程序.
Jef*_* To 38
通过将Google Caja HTML清理程序嵌入到Web工作者中,可以使其成为"Web就绪" .清理程序引入的任何全局变量都将包含在worker中,并且处理在其自己的线程中进行.
对于不支持Web Workers的浏览器,我们可以使用iframe作为清洁工的独立环境.Timothy Chien有一个polyfill就是这样做的,使用iframe模拟Web Workers,这样就可以为我们完成.
Caja项目有一个wiki页面,介绍如何使用Caja作为独立的客户端清洁剂:
anthtml-sanitizer-minified.js或html-css-sanitizer-minified.js在您的网页html_sanitize(...)工作者脚本只需要遵循这些说明:
importScripts('html-css-sanitizer-minified.js'); // or 'html-sanitizer-minified.js'
var urlTransformer, nameIdClassTransformer;
// customize if you need to filter URLs and/or ids/names/classes
urlTransformer = nameIdClassTransformer = function(s) { return s; };
// when we receive some HTML
self.onmessage = function(event) {
// sanitize, then send the result back
postMessage(html_sanitize(event.data, urlTransformer, nameIdClassTransformer));
};
Run Code Online (Sandbox Code Playgroud)
(需要更多代码才能使simworker库正常工作,但这对于此讨论并不重要.)
演示:https://dl.dropbox.com/u/291406/html-sanitize/demo.html
Sea*_*rds 17
永远不要相信客户.如果您正在编写服务器应用程序,请假设客户端将始终提交不卫生的恶意数据.这是一个经验法则,可以帮助您摆脱困境.如果可以的话,我会建议在服务器代码中进行所有验证和卫生,你知道(在合理的程度上)将无法摆弄.也许您可以使用服务器端Web应用程序作为客户端代码的代理,该代码从第三方获取并在将其发送到客户端之前进行卫生处理?
[编辑]对不起,我误解了这个问题.但是,我坚持我的建议.如果您在将服务器发送给服务器之前清理服务器,那么您的用户可能会更安全.
bob*_*nce 12
您无法预料到某些浏览器可能会绊倒以逃避黑名单的每种可能的奇怪类型的格式错误标记,因此请勿列入黑名单.有许多你可能需要的不仅仅是脚本/嵌入/对象和处理程序,除去更多的结构.
而是尝试将HTML解析为层次结构中的元素和属性,然后针对尽可能小的白名单运行所有元素和属性名称.还要检查您对白名单所允许的任何URL属性(请记住,有更多危险的协议,而不仅仅是javascript :).
如果输入是格式良好的XHTML,则上述的第一部分要容易得多.
像往常一样,如果您可以找到任何其他方法来避免这样做,请改为使用它.有许多潜在的漏洞.如果主要的网络邮件服务在这么多年后仍在寻找漏洞,那么是什么让你觉得你可以做得更好?
ald*_*del 11
现在所有主流浏览器都支持沙盒iframe,我认为有一种更简单的方法可以保证安全.如果这个答案可以由更熟悉这种安全问题的人审查,我会喜欢它.
注意:此方法肯定不适用于IE 9及更早版本.有关支持沙盒的浏览器版本,请参阅此表.
我们的想法是在禁用JavaScript的情况下创建隐藏的iframe,将不受信任的HTML粘贴到其中,然后让它进行解析.然后,您可以遍历DOM树并复制出被认为安全的标记和属性.
此处显示的白名单只是示例.白名单的最佳选择取决于应用程序.如果您需要比标签和属性的白名单更复杂的策略,则可以通过此方法来适应,但不是通过此示例代码.
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); // necessary so the iframe contains a document
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;
};
Run Code Online (Sandbox Code Playgroud)
你可以在这里试试.
请注意,我在此示例中禁止使用样式属性和标记.如果你允许它们,你可能想要解析CSS并确保它对你的目的是安全的.
我已经在几个现代浏览器(Chrome 40,Firefox 36 Beta,IE 11,Chrome for Android)和一个旧版本(IE 8)上进行了测试,以确保在执行任何脚本之前保存它.我有兴趣知道是否有任何浏览器有问题,或者我忽视的任何边缘情况.
所以,它是2016年,我想我们很多人现在都在使用npm代码中的模块.sanitize-html似乎是npm的主要选项,尽管还有其他选项.
这个问题的其他答案提供了很好的输入,如何推出自己的,但这是一个棘手的问题,经过充分测试的社区解决方案可能是最好的答案.
在命令行上运行以安装:
npm install --save sanitize-html
ES5:
var sanitizeHtml = require('sanitize-html');
// ...
var sanitized = sanitizeHtml(htmlInput);
ES6:
import sanitizeHtml from 'sanitize-html';
// ...
let sanitized = sanitizeHtml(htmlInput);
String.prototype.sanitizeHTML=function (white,black) {
if (!white) white="b|i|p|br";//allowed tags
if (!black) black="script|object|embed";//complete remove tags
var e=new RegExp("(<("+black+")[^>]*>.*</\\2>|(?!<[/]?("+white+")(\\s[^<]*>|[/]>|>))<[^<>]*>|(?!<[^<>\\s]+)\\s[^</>]+(?=[/>]))", "gi");
return this.replace(e,"");
}
Run Code Online (Sandbox Code Playgroud)
- 黑名单 - >完整删除标签和内容
- 白名单 - >保留标签
删除其他标签但保留标签内容
- 删除了白名单标签的所有属性(其余的)