4

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

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

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

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

到我的 PHP 页面。

由于我在安全方面真的没有太多经验,因为我这样做是一种爱好,有人可以向我解释使用 Access-Control-Allow-Origin: * 的安全风险吗?或者有没有更好的方法我应该考虑这样做?

4

5 回答 5

2

跨域资源共享 (CORS)是标头字段背后的规范,旨在允许通过XMLHttpRequestAccess-Control-Allow-Origin进行跨域请求,但通过提供允许服务器定义哪个跨域的接口来保护用户免受恶意站点读取响应请求是允许的,哪些是不允许的。所以 CORS 不仅仅是,它表示允许来自任何来源的 XHR 请求。Access-Control-Allow-Origin: *

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

于 2013-04-06T17:36:34.847 回答
1

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

正如 hek2mgl 所指出的,JSONP 可以很好地解决这个问题。您需要做的就是将 HTML 包装在 JSONP 包装器中,如下所示:

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

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

“我研究过的另一个选项是添加header("Access-Control-Allow-Origin: *");到我的 PHP 页面。由于我在安全方面真的没有太多经验,因为我这样做是出于一种爱好,有人可以向我解释一下使用中的安全风险Access-Control-Allow-Origin: *吗?”

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

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

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

“或者我应该研究一个更好的方法来做到这一点?”

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

于 2013-04-06T17:55:11.137 回答
1

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

你写了:

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

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

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

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

于 2013-04-06T17:05:42.460 回答
0

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

设置:

  • 一家银行,其网上银行服务器的 CORS 标头设置为接受所有(ACAO:*)(称为 A)
  • 登录的合法客户(称他们为 B)
  • 一个恰好能够让客户端运行任何东西的黑客(称它为 E)

A<->B 对话被认为是合法的。但是,如果黑客可以设法使标记 (B) 加载一个带有一些 JS 的站点,这些 JS 可以触发 AJAX 请求(很容易通过大型站点上的永久 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,就是这样。

一个很酷的旁注,CORS 不适用于 IE9 之前的任何东西。所以你需要构建一个后备,可能是 iframe 或 JSONP。

不久前,我写了关于这个主题的文章:http ://www.sebrenauld.co.uk/en/index/view/access-json-apis-remotely-using-javascript ,其形式比维基百科更快乐,由方法。这是一个我非常珍视的话题,因为我不得不多次与 API 开发作斗争。

于 2013-04-06T17:14:49.427 回答
0

CSRF(Cross Site Request Foregery) 的概念可以引起你的关注 http://en.wikipedia.org/wiki/Cross-site_request_forgery 有多种方法可以限制这个问题,最常用的技术是使用csrf token.

此外,您还应该Rate limiter为“限制执行从某个 ip 发出的数量请求”设置一个 IP,以限制如果您是目标可以进行的 DoS 攻击,您可以从如何限制我的网站的 API 用户?

于 2013-04-06T17:16:47.620 回答