虽然我同意@Alfonso 的回答中提出的漏洞,但情况实际上更糟:所有您的所有不受信任的变量都容易受到 XSS 攻击。
例如,
说untrustedURL包含以下文字
"><img src="http://example.com" onerror=alert(/xss/) data-x="
这将导致呈现以下内容:
<a class="url" href=""><img src="http://example.com" onerror="alert(/xss/)" data-x="">
这将导致 JavaScript 警报立即显示:
由于您的代码已经在 JavaScript 上下文中,您需要 follow Rule #1 of the OWASP XSS cheat sheet 和 HTML 编码数据。以下字符的简单转换就足够了:
& --> &
< --> <
> --> >
" --> "
' --> ' ' not recommended because its not in the HTML spec (See: section 24.4.1) ' is in the XML and XHTML specs.
/ --> / forward slash is included as it helps end an HTML entity
请注意,OWASP 建议将规则 #2 用于 HTML 属性值,但是如果您引用所有属性,那么以上内容就足够了。规则 #2 可以在任何地方使用,包括未引用的,所以如果你有混合规则 #2 会更简单。
我已阅读 your comment 关于你说你应该 encode Javascript after escaping HTML entities。
是的,这适用于值最初来自的位置(例如从服务器端),但您应该使用服务器端代码使用的语言进行此编码,而不是 JavaScript。另外,先进行 JavaScript 转义以将服务器端变量转换为 JavaScript,然后在 JavaScript 中使用 HTML 转义以准备插入 DOM。
例如ASP.NET C# 中的 JavaScript 转义:
<script>
var untrustedURL = "<%=HttpUtility.JavaScriptEncodeString(usersUrl)%>";
</script>
See my answer here for greater detail on this.
然后你需要使用一个函数进行 HTML 编码:
function escapeHTML (unsafe_str) {
return unsafe_str
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/\"/g, '"')
.replace(/\'/g, ''')
.replace(/\//g, '/')
}
所以你的代码可能只是
<script>
var untrustedURL = escapeHTML("<%=HttpUtility.JavaScriptEncodeString(usersUrl)%>");
</script>
untrustedURL 和 untrustedSource
请注意,这些是也应进行验证的特殊情况。您应该在服务器端执行此操作,并确保它们以 http://、https:// 或 // (protocol relative URL) 开头。白名单方法可确保用户无法输入 javascript: 方案 URL,并且还可以防止输入可能对用户的浏览器、操作系统、设备、配置等唯一的不同方案。仅允许 HTTP 更安全。