我要回答我自己的问题。在一遍又一遍地处理这种情况之后,解决方案非常明显,原因也很明显。
首先也是最重要的:插入到 javascript 中的任何字符串都需要是 javascript 安全的。无论如何,这总是需要发生:
<script>
var x = "<% encodeForJavaScript(someCrazyString) %>";
</script>
这里的目标是确保此声明的安全。由于这是 javascript 代码,因此将其视为 javascript--这不是 url,因此 url 编码不正确。
现在,如果x
要在 url 中使用它,则需要将其编码为 url。
唯一的事情是x
现在是一个 javascript 字符串。所以服务器端编码是不可能的,因为字符串被推出了中间层,现在在浏览器中生存和呼吸。
解决方法是使用javascript的url编码功能: encodeURIComponentz()
<script>
var x = "<% encodeForJavaScript(someCrazyString) %>";
x = x + '234'
var url = 'http://localhost/abc.cfm?x=' + encodeURIComponent(x)
</script>
从来没有理由使用 2 个服务器端 XXS 编码函数。始终使用单个服务器端编码函数并为上下文使用正确的服务器端函数:
网址:
<a href="xyz.jsp?x=<% encodeForURL(someString) %>" target="_blank" >click here</a>
js:
<script>
var x = "<% encodeForJavaScript(someCrazyString) %>";
</script>
json:
<script>
var x = {"x" : "<% encodeForJSONinJS(someCrazyString) %>"};
</script>
更新(几年后)
执行 2 次服务器端编码将获得与一次在服务器端和一次在客户端进行编码相同的结果。所以解决方案 3 是正确的,当且仅当var u
停留在 url 范围内。
进行 2 次服务器端编码的危险在于,您只能在第一次编码 的上下文中使用该片段。
以上面的示例为例,再添加 1 行:
<script>
var u = 'xyz.html?x=<% encodeForJavaScript(encodeForURL(url.baddata)) %>
dosomeAjax(u);
document.getElementById('someDivTag').innerHTML= u;
</script>
现在有问题,因为 u 是 url 编码的而不是 html 编码的。(在这种特殊情况下,这不会出现 xss 可变性,因为您无法将 url 编码的字符串分解到 js 范围内——尽管如此,还有许多其他情况需要对字符串进行 2x 编码)。
为了灵活性,我的偏好是在服务器上编码一次,并根据客户端的需要编码为:
<script>
var x = "<% encodeForJavaScript(someCrazyString) %>";
var u = 'http://localhost/abc.cfm?x=' + encodeURIComponent(x)
dosomeAjax(u);
document.getElementById('someDivTag').innerHTML= u.toHtml();
</script>
哪里toHtml()
是:
var __entityMap = {
"&": "&",
"<": "<",
">": ">",
'"': '"',
"'": ''',
"/": '/'
};
String.prototype.toHtml = function() {
return String(this).replace(/[&<>"'\/]/g, function (s) {
return __entityMap[s];
});
}
我正在检查 Cheran Shunmugavel 的答案是否正确。