8

我碰巧读到了 XSS 以及如何避免它。根据我的阅读,我了解到我们需要输入过滤、正确处理应用程序代码和输出编码,以使 Web 应用程序在某种程度上是 XSS 安全的。浏览了几篇文章后,仍然存在几个疑问。

  • 当我尝试jQuery.text("untrusted_data")element.text=untrusted_data时,浏览器似乎完美地编码了内容,但我在其他地方读到客户端编码不应该被信任,你必须“总是”在服务器端进行编码。为什么客户端编码被认为不安全?

  • 每当我尝试使用jQuery.val(untrusted_data)element.value=untrusted_data设置值时,它似乎就足够安全了。那么它真的是 XSS 安全还是我错过了这里的任何情况?

  • 另外,我碰巧在某处读到jQuery.setAttribute(attrName,untrusted_data)setAttribute(attrName,untrusted_data)仅当属性名称不包含基于 URL 上下文的属性(src、href 等)或事件处理程序( onClick、onMouseOver 等)。如果是这种情况,我应该如何使用 setAttribute("href",untrusted_data) 设置 href 属性?来自服务器端的 encodeForHtmlAttribute(untrusted_data) 是正确的方法吗?
  • 我应该如何处理动态 html 创建。考虑下面的例子

<div id="divName1" onClick="copyData()">untrusted_data</div> <div id="divName2"></div>

function copyData()
{
  var divValue = jQuery("#divName1").html();
  jQuery("#divName2").html(divValue);/XSS Here
}

我想在这里实现的是从 divName1 中获取文本并将其粘贴到 divName2 的内容中。我上面写的代码存在 XSS 漏洞。我可以将其更改为

jQuery("#divName2").text(divValue)

所以,这将确保编码,但据我了解,我们说客户端编码是不安全的,应该只使用服务器端编码。我应该如何在不使用客户端编码的情况下将其编写为 XSS 安全?我在这里有点困惑:(。请帮我解决这些疑问。

4

1 回答 1

8

这是一次很多问题。

为什么客户端编码被认为不安全?

只要正确且一致地完成,客户端编码就可以了。客户端编码通常具有较低的标准,因为它不需要担心字符编码级别的攻击,如 UTF-7 攻击。

每当我尝试使用 jQuery.val(untrusted_data) 或 element.value=untrusted_data 设置值时,它似乎就足够安全了。那么它真的是 XSS 安全还是我错过了这里的任何情况?

假设untrusted_data是一个字符串,并且正在设置其值的元素是流或块元素中的常规文本节点,那么你很好。如果分配值的节点是<script>元素或 URL、事件处理程序或样式属性节点或任何与<object>.

此外,我碰巧在某处读到 jQuery.setAttribute(attrName,untrusted_data) 和 setAttribute(attrName,untrusted_data) 仅当属性名称不包含基于 URL 上下文的属性(src、href 等)或事件处理程序( onClick、onMouseOver 等)。如果是这样的话,

这是部分正确的。其他属性具有尖锐的边缘,例如与和、和style相关的许多事物。<object><embed><meta>

如果您对该属性不太了解,请不要将其暴露给不受信任的数据。通常安全的东西是包含文本内容的属性,title例如dir=ltrdir=rtl

一旦您处理了具有更复杂值的属性,您就面临攻击者利用诸如属性-moz-binding中的晦涩浏览器扩展的风险。style

似乎足够安全

在你踩到它们之前,地雷似乎是安全的。

你不能从“看起来很安全”的事情中得出很多结论。您确实需要查看它并了解可能出现的问题,并安排事情,以便只有在出现完美风暴时才会有风险(P(灾难)= P(failure0)* P(failure1) ) * ...) 并且当只有一件事情出错时,您没有风险 (P(disaster) = P(failure0) + P(failure1)*P(!failure0) + ...)。

我应该如何使用 setAttribute("href",untrusted_data) 设置 href 属性?

不要在没有将协议列入白名单的情况下这样做。

if (!/^https?:\/\//i.test(untrusted_data) && !/^mailto:/i.test(untrusted_data)) {
  throw new Error('unsafe');
}

来自服务器端的 encodeForHtmlAttribute(untrusted_data) 是正确的方法吗?

否。HTML 编码传递给的值setAttribute是多余的,无助于保留任何安全属性。 <iframe srcdoc>可能是一个罕见的例外,因为如果我对最近规范更改的回忆是正确的,它的内容是 HTML。

我想在这里实现的是从 divName1 中获取文本并将其粘贴到 divName2 的内容中。我上面写的代码存在 XSS 漏洞。

不要乱用 HTML。浏览器的.innerHTMLgetter 有问题,有时会导致漏洞,例如反引号在 IE 中充当值分隔符。只需将节点从一个克隆到另一个。像下面这样的东西应该这样做:

var div1 = $('#divName1');
for (var child = div1[0].firstChild(); child; child = child.nextSibling) {
  $('#divName2').append([child.cloneNode(true)]);
}

我可以将其更改为

jQuery("#divName2").text(divValue)

如果您想要的只是文本内容,那很好。

于 2012-11-20T08:10:45.980 回答