【问题标题】:DOM based XSS is possible in this example?在这个例子中基于 DOM 的 XSS 是可能的吗?
【发布时间】:2015-05-18 09:57:35
【问题描述】:

我一直在阅读大量有关基于 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;

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

【问题讨论】:

  • 什么是${untrustedURL}?你在运行模板引擎还是什么?
  • @Sharky 这是 ES6 模板字符串。
  • 为不受信任的 url 提供一个值,例如 var untrustedURL = '"&gt;&amp;nbsp;&lt;/a&gt;&lt;script&gt;alert("XSS");&lt;/script&gt;&lt;a href="#"&gt;'; 我还没有使用 ES6,但我认为它会以这种方式进行 XSS。

标签: javascript security xss ecmascript-6


【解决方案1】:

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

由于您的代码已经在 J​​avaScript 上下文中,您需要 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 关于你说你应该 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, '&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 更安全。

【讨论】:

  • 我想我现在对 XSS 有了更好的理解。非常感谢您的回答。顺便说一句,如果这些属性没有被引用,我应该遵循 OWASP XSS Cheat Sheet Rule #2 吗?
  • @Tresdin:没问题。对,那是正确的。我在这里没有提到它的原因是因为在你的代码中引用了它们,我想让事情简单明了。您可以调整 escapeHTML 函数来编码除字母数字以外的所有内容。
【解决方案2】:

通过 url 和图像的来源,一个不受信任的值将是,例如:

javascript:evilStuff()

在链接的情况下,代码将在用户单击它时运行,而在图像源的情况下,它将在浏览器尝试加载图像时运行。请注意,图像 src 的技术仅适用于旧浏览器,现代浏览器会忽略它。我在链接中看到的另一个问题是,例如,您可能会获得一个将您定向到网络钓鱼网站的链接!

只有当您在代码中的其他地方使用该值并且以可能有害的方式使用该值时,才会使 data-value 属性易受攻击,否则,我看不到那里的危险。

至于 span 的内容,如果不转义 HTML 字符,几乎可以在其中插入任何内容。脚本标签、iframe、图像等...请注意,这适用于您在任何地方插入的所有不安全值。

恶意人员可以在您不转义 HTML 实体的任何地方插入任何 HTML。

我认为,解决方案始终是转义/剥离标签和某些值。例如,为了防止用户在动态 href 中插入危险的 url,您可以应用一个正则表达式,从字符串的开头删除单词 javascript:,或者检查无效的 url(不同的域、不寻常的字符、格式错误的网址等)。

【讨论】:

  • 我现在明白 XSS 强烈依赖于执行上下文。感谢您的精彩解释。顺便说一句,OWASP 建议在转义 HTML 实体后使用 encode Javascript。编码 Javascript 是关于使用 \xHH 格式转义所有非字母数字字符。你知道如何在 Javascript 中实现这一点吗?
  • data-value 属性如果不转义,则与其他所有属性一样容易受到攻击:您可以突破属性(和标签)。
【解决方案3】:

假设 ${untrustedText} 不是 HTML 转义的,请尝试将其设置为:

<div style="position:fixed;left:0;right:0;top:0;bottom:0;"
  onmousemove="this.style.display='none';alert('XSS');"></div>

【讨论】:

  • 甚至只是&lt;img src=x:x onerror=alert(document.domain)&gt;
猜你喜欢
  • 1970-01-01
  • 2017-10-12
  • 2015-11-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多