为什么跨域Ajax是一个安全问题?

时间:2009-01-21 20:01:17

标签: ajax security xss

为什么决定使用 XMLHTTPRequest 进行XML调用不应该跨域边界调用?您可以检索JavaScript,图片,CSS,iframe以及我能从其他域中想到的任何其他内容。为什么不允许Ajax HTTP请求跨越域边界?考虑到我可以看到它被滥用的唯一方式,这似乎是一个奇怪的限制,如果有人将Javascript注入页面。但是,在这种情况下,您只需向文档中添加img,script或iframe元素,即可让它请求第三方URL并将其发送到服务器。

[编辑]

有些答案指出了以下原因,让我们指出它们没有产生禁止这种情况的主要原因的原因。

XSRF(跨站点请求伪造,也称为CSRF,XSRF)

你可以在不使用它的情况下进行XSRF攻击。作为一般规则,XMLHTTPRequest根本不被使用,仅仅是因为以与所有主流浏览器兼容的方式制作XMLHTTPRequest非常困难。如果您希望他们加载您的网址,只需向网址添加img标记就会容易得多。

发布到第三方网站

<script type="text/javascript">
  $.post("http://some-bank.com/transfer-money.php", 
         { amount: "10000", to_account: "xxxx" })
</script>

可以用

完成
<body onload="document.getElementById('InvisbleForm').submit()"
    <div style="display:none">
        <form id="InvisbleForm" action="http://some-bank.com/transfer-money.php" method="POST">
            <input type="hidden" name="amount" value="10000">
            <input type="hidden" name="to_account" value="xxxxx">
        </form>
    </div>
</body>

JPunyon:为什么要将漏洞留在新功能中

你不会再造成任何不安全感。您只是想要以良好的方式使用它的开发人员感到不安。任何想要将此功能用于邪恶(也称为真棒)的人都可以使用其他方法来实现它。

结论

我将 bobince 的答案标记为正确,因为他指出了关键问题。因为XMLHTTPRequest允许您使用凭据(cookie)发布到目标站点,并读取从站点发回的数据,以及发送人员凭据,您可以编排一些提交一系列表单的JavaScript,包括确认表单,完成生成的任何随机密钥,以防止XSRF。通过这种方式,您可以浏览目标网站,例如银行,银行的网络服务器将无法确定是否只是提交所有这些表单的普通用户。

9 个答案:

答案 0 :(得分:36)

  

为什么不允许Ajax HTTP请求跨越域边界。

因为AJAX请求是(a)使用用户凭据提交的,并且(b)允许调用者读取返回的数据。

这些因素的组合可能会导致漏洞。有人建议添加一种省略用户凭证的跨域AJAX形式。

  

您只需将img,script或iframe元素添加到文档

即可

这些方法都不允许调用者读取返回的数据。

(除了脚本之外,它是故意设置允许的,允许跨域脚本编写 - 或者有人做出可怕的蠢事。)

  

你可以完全不使用它来进行XSS攻击。发布到第三方网站

这不是XSS攻击。这是一个跨站点请求伪造攻击(XSRF)。有一些已知的解决XSRF攻击的方法,例如包括一次性或加密令牌,以验证提交是故意来自用户的,而不是从攻击者代码启动。

如果您允许跨域AJAX,您将失去此安全措施。攻击代码可以从银行站点请求页面,读取其上的任何授权令牌,并在第二个AJAX请求中提交它们以执行传输。并且成为跨站点脚本攻击。

答案 1 :(得分:7)

POST之间的一个重要区别:

<body onload="document.getElementById('InvisbleForm').submit()" ...

和Ajax是在执行任何POST之后,浏览器将替换页面并在执行Ajax调用之后 - 而不是。 POST的结果将是:

  1. 用户清楚可见。
  2. 攻击将在此时停留,因为来自my-bank.com的响应页面将获得控制权。没有银行会实施一键转移
  3. 如果允许跨域Ajax,XSRF的场景将如下所示:

    1. 用户以某种方式访问​​www.bad-guy.com
    2. 如果在其他浏览器实例中没有打开my-bank.com页面,则攻击不成功。
    3. 但是如果这样的页面被打开并且用户已经输入了他的用户名/密码,这意味着该会话在浏览器的缓存中有一个cookie。
    4. www.bad-guy.com页面上的JavaScript代码向my-bank.com发出Ajax调用。
    5. 对于浏览器,这是一个常规的HTTP调用,它必须将my-bank cookie发送到my-bank.com并发送它们。
    6. 银行处理此请求,因为它无法将此通话与用户的常规活动区分开来。
    7. JavaScript代码可以读取响应的事实并不重要。在攻击案例中,这可能没有必要。真正重要的是计算机前面的用户不知道这种交互发生了。他将在www.bad-guy.com页面上查看漂亮的图片。
    8. 如果需要,JavaScript代码会对my-bank.com进行多次其他调用。
    9. 要点是不需要注射或任何页面篡改。

      更好的解决方案可能是允许呼叫本身但不发送任何cookie。这是一个非常简单的解决方案,不需要任何广泛的开发。在许多情况下,Ajax呼叫进入不受保护的位置,不发送cookie不会受到限制。

      现在正在讨论的CORS(跨源资源共享),其中包括发送/不发送cookie。

答案 2 :(得分:2)

嗯,显然你并不是唯一一个有这种感觉的人......

http://www.google.com/search?q=xmlhttp+cross+site

编辑:上述搜索中有一个有趣的讨论:

http://blogs.msdn.com/ie/archive/2008/06/23/securing-cross-site-xmlhttprequest.aspx

看起来正在提出允许跨站点xmlhttp请求(IE 8,FF3等)的提议,虽然我希望他们在我为我的网站编写代码时一直在那里:) 然后是兼容性的问题......在无处不在之前还需要一段时间。

答案 3 :(得分:2)

当您向服务器发送HTTP请求时,服务器设置的cookie也会由浏览器发送回服务器。服务器使用这些cookie来确定用户登录等事实

这可以被恶意攻击者利用,在某些JavaScript的帮助下,恶意攻击者可以在其他网站上窃取信息或执行未经授权的命令而无需用户了解此事。

例如,可以要求用户访问具有以下JavaScript代码的网站(假设jQuery):

<script type="text/javascript">
  $.post("http://some-bank.com/transfer-money.php", 
         { amount: "10000", to_account: "xxxx" })
</script>

现在,如果用户在执行上述代码时确实已登录银行,则攻击者可能已将10,000美元转入XXX帐户。

这种攻击称为跨站点请求伪造(XSRF)。有关Wikipedia的更多相关信息。

这主要是由于这个原因存在同源策略,并且浏览器不允许您在与源不同的域上执行XMLHttpRequests。

有一些讨论正在进行实际允许跨域XHR,但我们必须看看这是否真的被接受了。

答案 4 :(得分:1)

这是一个令人担忧的问题,因为它可以用于不良目的,正如您所提到的那样。它也可以用于良好的意图,因此,正在开发跨域协议。

最大的两个问题是它与跨站点脚本(XSS)和跨站点请求伪造(CSRF)结合使用。两者都是严重的威胁(这就是他们进入OWASP前十名和SANS 25的原因)。

  

我能看到它被滥用的唯一方法就是有人要注入Javascript

这是XSS太多的应用程序仍然容易受到攻击,如果浏览器安全模型不能阻止X域AJAX,他们就会向用户开放相当大的攻击媒介。

  

您只需在文档中添加img,script或iframe元素即可让它请求第三方网址

是的,但是那些会发送HTTP_REFERRER并且(通过其他方式)可以被阻止以防止CSRF。 AJAX调用可以更容易地欺骗标题,并允许其他方法绕过传统的CSRF保护。

答案 5 :(得分:1)

我认为将此与普通XSRF攻击分开的另一件事是你可以通过javascript对你得到的数据进行处理。

答案 6 :(得分:1)

我不知道最大的问题是什么?将AJAX呼叫发送到发送到您的应用程序的其他域名,然后转发到其他地方并使用过滤后的数据,如果确实需要,则解析返回的数据,然后将其提供给用户。

处理敏感的AJAX请求?通过检查标题,存储会话时间数据或将传入的IP地址过滤到您信任的来源或您的应用程序来确认传入的吸盘。

我个人希望将来看到的是,默认情况下,Web服务器,框架和CMS上的所有传入请求都具有坚如磐石的安全性,然后明确定义将解析来自外部源的请求的资源。

答案 7 :(得分:1)

使用<form>您可以发布数据,但无法阅读。使用XHR,您可以同时执行这两项操作。

http://bank.example.com/display_my_password这样的页面对XSRF是安全的(假设它只显示而不是设置密码)和帧(它们具有同源策略)。但是,跨域XHR将是一个漏洞。

答案 8 :(得分:0)

您将毫无戒心的访问者变为拒绝服务攻击者。

另外,想象一个跨站点脚本窃取你所有的Facebook东西。它打开一个IFrame并导航到Facebook.com

您已经登录到facebook(cookie),它会读取您的数据/朋友。还有更多的恶意。