1

我想让我的应用程序的用户能够在他们的网站上放置一些代码,并通过 jsonp 请求与我的服务器进行最少的交互。但是,我只希望远程请求能够来自我特别允许的远程站点。基本上,用户必须拥有我的应用程序的帐户。

为了安全起见,我的计划是:

  1. 在允许将代码放置在站点上之前,要存储请求将来自的域。
  2. 当服务器接收到远程请求时,它会从请求中获取域名并将其与数据库进行匹配。
  3. 如果域匹配,则验证请求并返回数据等。如果它不同,我将假设它是某种 XSS 攻击并拒绝请求,向远程返回错误。

如何获取请求来自的域?为了在我的开发盒上进行测试,我设置了一个在不同端口上运行的单独静态网站

Server domain: localhost:8090
Remote domain: localhost:8095

使用 getRemoteHost 似乎返回 127.0.0.1。在现实世界的情况下,这是否是远程域的 ip,然后是否有可能从该 ip 中找到人类可读的域名版本?存储和匹配 ip 可能不是一个好主意,因为我不知道尝试连接到我的服务的远程站点是否是从动态 ip 提供的......

也许我在这里采取了错误的方法,所以如果我错了,请纠正我。无法向远程站点的用户请求用户名和密码,因为他们没有实际帐户。

也许更好的方法是将某种加密令牌存储在数据库中而不是域中,当我向用户提供代码片段以放置在他们的站点上时,它可能包含一个隐藏的输入,其中包含此加密版本每个请求都传递的令牌?但是,在这种情况下,是否任何人都无法通过查看页面源来复制隐藏元素并具有对服务器的相同访问权限?

4

1 回答 1

3

一方面,您说“我只希望远程请求能够来自我特别允许的远程站点”,但使用 JSONP 意味着您不会看到来自远程站点的请求——您将看到请求来自访问远程站点的浏览器。这种区别很微妙但很重要,因为它严重限制了您的选择。

如果您想知道哪个站点发起了 JSONP 请求,可以查看 Referer 标头。除了......你不能依赖它被设置,尤其是在 HTTP/HTTPS 转换中。然后您可能会想“嘿,我将使用CORS ”,但是当然,任何人都可以使用他们想要的任何标头创建请求。我可以编写一个声称是您的远程站点之一的 HTTP 客户端,并使用它们的凭据访问您的界面——因此,如果标头是您限制访问的唯一方法,请知道它很容易被击败。

Referer 标头上方的下一步是颁发令牌并使用这些令牌进行识别。但是,正如您所指出的,远程站点必须将其提供给浏览器,以便浏览器创建请求。因此,有人可以复制它并在任何地方使用它。回到同一个问题。

您可以做的下一件事是发布令牌(用于识别)以及共享秘密(用于授权)。然后,您可以要求远程站点使用共享密钥对请求进行签名——说“是的,实际上是我,远程站点”。这样,远程站点给用户的浏览器签名,而不是秘密本身。您需要确保您签署的内容足以验证远程站点的意图(即站点希望用户浏览器执行的任何操作),并且它应该包含一个时间戳以防止重放攻击。这需要来自远程站点的一些服务器端计算,但会阻止用户采取任何操作,除非远程站点明确允许。

但是...您提到这些远程站点上的用户将没有帐户。如果这意味着它们可供公众使用,那么任何人都可以获取这些远程站点之一,提取签名,然后自己使用它来执行远程站点用户可以执行的相同操作。这不是实现的问题,而是架构的问题:您的设计要求随机的 Web 浏览器与您的服务交互,根本没有办法阻止man-in-the-middle。使用共享密钥可以让您在一定程度上进行控制,但您无法阻止它。

在这一点上,我建议您退后一步,考虑一下您实际上要解决的问题。这个界面有什么作用?这些远程站点上的浏览器是否需要直接与您交互?你想阻止谁,为什么?如果他们绕过你的检查会发生什么?

于 2012-09-22T16:07:00.040 回答