javascript - 在这个例子中,基于 DOM 的 XSS 是可能的吗?

标签 javascript security xss ecmascript-6

我已经阅读了一堆关于基于 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;

攻击者如何利用此代码的漏洞?解决方案是什么?

最佳答案

虽然我同意@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 警报立即显示:

ESS XSS

由于您的代码已经全部在 JavaScript 上下文中,因此您需要 follow Rule #1 of the OWASP XSS cheat sheet和 HTML 对数据进行编码。以下字符的简单转换就足够了:

 & --> &amp;
 < --> &lt;
 > --> &gt;
 " --> &quot;
 ' --> &#x27;     &apos; not recommended because its not in the HTML spec (See: section 24.4.1) &apos; is in the XML and XHTML specs.
 / --> &#x2F;     forward slash is included as it helps end an HTML entity

请注意,OWASP 推荐规则 #2 用于 HTML 属性值,但是如果您引用所有属性,那么以上内容就足够了。规则 #2 适用于任何地方,包括未引用的内容,因此如果您有混合规则 #2 会更简单。

我读过 your comment关于你说你应该在转义 HTML 实体后编码 Javascript

是的,这适用于值的初始来源(比如来自服务器端),但您应该使用服务器端代码使用的语言而不是 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, '&amp;')
      .replace(/</g, '&lt;')
      .replace(/>/g, '&gt;')
      .replace(/\"/g, '&quot;')
      .replace(/\'/g, '&#39;')
      .replace(/\//g, '&#x2F;')
}

所以你的代码可以是

<script>
var untrustedURL = escapeHTML("<%=HttpUtility.JavaScriptEncodeString(usersUrl)%>");
</script>

untrustedURLuntrustedSource

请注意,这些是也应进行验证的特殊情况。您应该在服务器端执行此操作,并确保它们以 http://https://// 开头( protocol relative URL)。白名单方法可确保用户无法输入 javascript: 方案 URL,并且还将防止输入对用户的浏览器、操作系统、设备、配置等可能是唯一的不同方案。仅允许 HTTP 更安全。

关于javascript - 在这个例子中,基于 DOM 的 XSS 是可能的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30300161/

相关文章:

javascript - 'ng build' 包含子文件夹中的所有脚本

java - 如何更改最近应用列表显示的快照?

spring - Spring Security 的自定义访问规则

javascript - Laravel:在允许 HTML 标签时,针对 XSS 清理用户输入

javascript - 禁用 div 中的所有 javascript

javascript - REPL 中的 Require() 似乎无法正常工作

javascript - Rails 中的 Css 文件分离(变慢)

javascript - Codeigniter 中的组合框

java - 如何为小程序配置新的安全对话框?

javascript - 这段代码容易受到 XSS 攻击吗?