我一直在阅读有关基于DOM的XSS的一系列文档,但我仍然无法弄明白。让我们来看看我的例子。
var html = `
<a class="url" href="${untrustedURL}">
<img src="${untrustedSource}">
</a>
<span class="name" data-value="${untrustedValue}">${untrustedText}</span>
`;
document.querySelector('#user').innerHTML = html;
攻击者如何利用此代码的漏洞?什么是解决方案?
答案 0 :(得分:3)
通过网址和图片来源,不受信任的值将是,例如:
javascript:evilStuff()
对于链接,代码将在用户单击时运行,对于图像的源,它将在浏览器尝试加载图像时运行。请注意,图像src的技术仅适用于旧版浏览器,现代版本将忽略它。我在链接中看到的另一个问题是,例如,您可以获得指向钓鱼网站的链接!
只有当您在代码中的其他位置使用该值时,数据值属性才会变得容易受到攻击,并且可能有害,否则,我不会在那里看到危险。
至于跨度的内容,如果你不转义HTML字符,几乎任何东西都可以插入其中。脚本标签,iframe,图像等...请注意,您在任何地方插入的所有不安全值都是如此。
恶意的人可以在任何您无法逃脱HTML实体的地方插入任何HTML。
我认为,解决方案始终是逃避/剥离标签和某些值。例如,为了防止用户在动态href中插入危险的URL,您可以应用从字符串开头删除单词javascript:
的正则表达式,或检查无效的URL(不同的域,不寻常)字符,格式错误的网址等。)
答案 1 :(得分:3)
虽然我同意@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建议HTML属性值使用规则#2,但是如果引用所有属性,则上述内容就足够了。规则#2适用于所有地方,包括不加引号,因此如果你有混合规则#2将更简单。
我已经阅读了your comment关于你说你应该encode Javascript after escaping HTML entities
。
是的,这适用于最初来自(例如来自服务器端)的值,但您应该使用服务器端代码使用的语言进行此编码,而不是JavaScript。此外,首先执行JavaScript转义以将服务器端变量转换为JavaScript,然后在JavaScript中使用HTML转义以准备插入DOM。
e.g。 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很多更安全。
答案 2 :(得分:0)
假设${untrustedText}
未进行HTML转义,请尝试将其设置为,例如:
<div style="position:fixed;left:0;right:0;top:0;bottom:0;"
onmousemove="this.style.display='none';alert('XSS');"></div>