有没有安全的方法来允许跨站点AJAX请求?

时间:2013-04-06 17:03:25

标签: php jquery ajax security cross-domain

我目前正在开发一个网站所有者可以安装的脚本,该脚本允许用户突出显示一个单词,并在一个小弹出div中查看该单词的定义。我只是在业余时间做这个业余爱好而无意出售它或任何东西,但我仍然希望它是安全的。

当文本突出显示时,它会向我的域发送一个AJAX请求到一个PHP页面,然后在数据库中查找该单词并输出包含该信息的div。据我所知,同源策略禁止我使用普通的AJAX完成此操作,但我也不能使用JSONP,因为我需要返回HTML,而不是JSON。

我研究过的另一个选择是添加

header("Access-Control-Allow-Origin: *");

到我的PHP页面。

由于我真的没有太多的安全经验,因为我这样做是为了一个爱好,有人可以向我解释使用Access-Control-Allow-Origin:*的安全风险吗? 或者我有更好的方法来做这件事吗?

5 个答案:

答案 0 :(得分:2)

Cross-Origin Resource Sharing (CORS)Access-Control-Allow-Origin标头字段后面的规范,是为了通过XMLHttpRequest允许跨源请求而建立的,但通过提供一个接口来保护用户免受恶意网站的攻击允许server to define which cross-origin requests are allowed and which are not。因此,CORS不仅仅是Access-Control-Allow-Origin: *,这表示允许来自任何来源的XHR请求。

现在提出您的问题:假设您的服务是公开的并且不需要任何身份验证,使用Access-Control-Allow-Origin: *来允许来自任何来源的XHR请求是安全的。但请确保仅在您希望允许该访问策略的那些脚本中发送该标头字段。

答案 1 :(得分:1)

JSONP应该符合您的需求。它是一种广泛部署的Web技术,旨在解决跨域问题。您还应该了解CORS,它解决了JSONP的一些缺点。我给你的链接还将包含有关这些技术的安全注意事项的信息。

您写道:

  

但我也不能使用JSONP,因为我需要返回HTML,而不是JSON。

为什么不呢?您可以使用这样的JSONP响应:

callback({'content':'<div class="myclass">...</div>'});

然后使用DOM操作将result.content注入当前页面。

答案 2 :(得分:1)

  

“当文本突出显示时,它向我的域发送一个AJAX请求到一个PHP页面,然后在数据库中查找单词并输出包含信息的div。我知道同源策略禁止我完成这与普通的AJAX,但我也不能使用JSONP,因为我需要返回HTML,而不是JSON。“

正如hek2mgl所说,JSONP可以正常工作。您需要做的就是将您的HTML包装在JSONP包装器中,如下所示:

displayDefinition({"word": "example", "definition": "<div>HTML text...</div>"});

其中displayDefinition()是一个JS函数,它显示一个带有给定HTML代码的弹出窗口(并且可能会将其缓存以供以后使用)。

  

“我调查的另一个选项是将header("Access-Control-Allow-Origin: *");添加到我的PHP页面。因为我真的没有太多的安全经验,因为我这样做是为了一个爱好,有人可以向我解释使用Access-Control-Allow-Origin: *

时的安全风险

风险与JSONP基本相同;在任何一种情况下,你都允许任何网站对你的脚本做任意的GET请求(他们实际上可以做到这一点)并读取结果(使用普通的JSON,他们通常不能,尽管旧的浏览器可能有一些安全漏洞,可以允许这个)。特别是,如果用户在登录您的站点时访问恶意网站,并且您的站点可能通过JSONP或CORS公开敏感用户数据,则恶意站点可以访问此类数据。

对于您描述的用例,任何一种方法都应该是安全的,只要您只将它用于该特定脚本,并且只要脚本只执行您所描述的操作(查找单词并返回其定义)

当然,对于您不希望任何网站访问的脚本,您也不应该使用CORS或JSONP,例如银行转帐表单。这些脚本,如果他们可以修改服务器上的数据,通常还需要使用额外的防御措施,如anti-CSRF tokens,以防止“盲目”的CSRF攻击,攻击者并不真正关心响应,而只是关于侧面请求的效果。显然,反CSRF令牌本身就是敏感的用户特定数据,因此不应通过CORS,JSONP或绕过同源保护的任何其他方法获得。

  

“或者我有更好的方式来做这件事吗?”

另一种方法(尽管不一定更好)可以让您的PHP脚本将定义作为HTML返回,并且弹出窗口只包含指向脚本的iframe元素。

答案 3 :(得分:0)

CORS问题很简单 - 您是否希望任何人能够远程AJAX您的域名?如果您的表格容易出现CSRF,这可能会非常危险。这是一个直接从我脑海中拔出的例子。

设置:

  • 一家银行,其网上银行服务器的CORS标头设置为全部接受(ACAO:*)(称之为A)
  • 登录的合法客户(称为B)
  • 一个碰巧能够使客户端运行任何东西的黑客(称之为E)

A&lt; - &gt; B对话被视为合法。但是,如果黑客可以设法使标记(B)加载一个可以触发AJAX请求的JS(通过大型网站上的永久XSS漏洞很容易),他/她可以让B向A发起请求通过JSON,被允许并被视为正常请求

你可以做这么多可怕的事情。想象一下,银行的表格输入如下:

POST:
* targetAccountID -> the account that will receive money
* money -> the amount to be transferred

如果标记已登录,我可以注入:

$.ajax({ url: "http://A/money.transfer.php"; data { targetAccountID: 123; money: 9999; }; });

突然之间,访问该网站并登录到A的任何人都会看到他们的帐户耗尽了9999个单位。

这个是为什么CORS需要少量盐 - 实际上,不要打开超过你需要打开的东西。打开你的API就是这样。

很酷的一面,在IE9之前,CORS不起作用。因此,您需要构建一个后备,可能是iframe或JSONP。

我在不久前写过这个话题:http://www.sebrenauld.co.uk/en/index/view/access-json-apis-remotely-using-javascript顺便说一下比维基百科更快乐的形式。这是我心中所珍视的话题,因为我不得不多次与API开发竞争。

答案 4 :(得分:0)

CSRF(跨站点请求外观)的概念可能是您关心的问题   http://en.wikipedia.org/wiki/Cross-site_request_forgery   有多种方法可以限制此问题,最常用的技术是使用csrf token

此外,您还应该将基于IP的Rate limiter用于“限制执行从某个IP发出的号码请求”,以限制如果您是目标可以执行的DoS攻击,您可以寻求一些来自How do I throttle my site's API users?

的帮助