关于XSS的一些澄清

时间:2012-11-20 07:59:42

标签: java javascript jquery xss

我碰巧读到了关于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”)。文本(divValue)

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

1 个答案:

答案 0 :(得分:8)

这是很多问题。

  

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

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

  

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

假设untrusted_data是一个字符串,并且正在设置其值的元素是flow或block元素中的常规文本节点,那么你没问题。如果正在分配其值的节点是<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(失败0)* P(失败1) )* ...)并且当只有一件事出错时你没有风险(P(灾难)= P(失败0)+ P(失败1)* 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)是正确的接近方式吗?

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

  

我想在这里实现的是从divName1获取文本并将其粘贴到divName2的内容。我上面写的代码是易受攻击的XSS。

不要乱用HTML。浏览器的.innerHTML getter是错误的,有时会导致漏洞利用,就像在IE中作为值分隔符的反引号一样。只需将节点从一个克隆到另一个。像下面这样的东西应该这样做:

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

我可以将其更改为

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

如果您想要的只是文字内容,那就没问题了。