以下是用户在站点上创建的页面的简化示例(他们通过填写表单创建它,然后他们获取页面的URL;下面是他们创建的页面的HTML)。
在示例中,我将获取隐藏输入字段的值,然后将其按原样放入DOM中。这会导致警报,模拟XSS攻击。
防止这样的事情的最佳方法是什么? #sourceinput的值以前是由查看下面页面的相同或不同用户输入的,并且未过滤用户的输入以删除标记。 (实际案例涉及jquery.tooltip.js插件及其bodyHandler回调;在鼠标悬停时,bodyHandler回调将获取隐藏的输入并将其显示给用户。)
解决这个问题的一种方法是在输入上删除标签;我控制隐藏文本字段中的内容,以便解决它。
另一种方法是在Javascript中剥离标签,但其中一些似乎不是100%有效:
Strip HTML from Text JavaScript
我是否缺少某种最佳实践,或者这两种最佳方式?
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<head>
<title></title>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script>google.load("jquery", "1.7.1");</script>
<script>
$(document).ready(function() {
var badHTML = $('#sourceinput').val();
$('#destinationdiv').html( badHTML );
//$('#destinationdiv').text( badHTML );
});
</script>
</head>
<body>
<input type="hidden" id="sourceinput" value="<script>alert('hi');</script>" />
<div id="destinationdiv" style="width:10px;height:10px;background-color:red;"></div>
</body>
</html>
更新:我现在要解决的问题有三个部分:
当保存用户创建的页面时,我在其输入上运行PHP的strip_tags()。这些只是简短的文本字符串,如标题和blurbs,因此很少有用户希望他们可以输入HTML。这可能不适合其他情况。
当显示用户创建的页面时,我将其输入放在div中,而不是将用户输入的内容放入输入值属性中。
我使用.text()(不是.html())从该div中取出值。然后我通过下划线功能运行它(见下文)。
测试这一点 - 包括模拟跳过第一步 - 似乎有效。至少我希望没有我错过的东西。
答案 0 :(得分:0)
如果您不想使用整个Underscore函数库,那么Underscore.js使用的转义函数就在这里:
var escape = function(string) {
return (''+string).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''').replace(/\//g,'/');
};
像
一样使用var safe_html = escape("<b>Potentially unsafe text</b>"); // "<b>hello</b>"
$("#destination").html(safe_html);
它写得很好并且知道可以工作,所以我建议不要自己动手。
答案 1 :(得分:0)
我会说你评论的内容(使用来自jquery的text()是更好的选择)。这将确保文本保留您想要的文本。过滤或剥离可能会产生不必要的副作用,例如在输入中删除数学表达式(“x is&lt; 5”)。
答案 2 :(得分:0)
什么都不做。
您正在尝试保护用户免受他/她的侵害。用户A无法对用户B造成伤害。对于您所关心的一切,用户A也可以在地址栏上键入javascript:alert('hi')
并自己输入xss。无论你创建什么javascript转义功能,精明的用户总能绕过它。总而言之,这是一种毫无意义的追求。
现在,如果您开始保存用户在服务器端输入的内容,那么您一定要过滤掉内容。不要自己构建任何东西。根据您的服务器端语言,有几个选项。 OWASP's AntiSammy就是这样一种解决方案。
如果您确实选择在服务器端保存用户输入的html,请确保在将其保存到数据库之前通过antisammy或类似的库运行它。在出路的时候,你应该简单地转储HTML而不转义,因为你知道数据库中的任何东西都被清理了。