代码之家  ›  专栏  ›  技术社区  ›  Jiew Meng

API网关lambda CORS处理程序。安全获取源站

  •  7
  • Jiew Meng  · 技术社区  · 6 年前

    我想为多个起源实现CORS,我理解我需要通过lambda函数来实现,因为我不能通过mock方法来实现这一点。

    exports.handler = async (event) => {
      const corsUrls = (process.env.CORS_URLS || '').split(',')
      const requestOrigin = (event.headers && event.headers.origin) || ''
    
      if (corsUrls.includes(requestOrigin)) {
        return {
          statusCode: 204,
          headers: {
            "Access-Control-Allow-Headers": 'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Requested-With',
            'Access-Control-Allow-Origin': requestOrigin,
            'Access-Control-Allow-Methods': 'POST,DELETE,OPTIONS'
          }
        }
      }
    
      return {
        statusCode: 403,
        body: JSON.stringify({
          status: 'Invalid CORS origin'
        })
      }
    }
    

    首先,上面看起来还可以吗?然后我从标题中得到原点 event.headers.origin . 但我发现我可以手动设置头部“绕过”CORS。是否有可靠的方法检测源域?

    2 回复  |  直到 6 年前
        1
  •  3
  •   Charlie Fish    6 年前

    首先,上面看起来还可以吗?

    你的代码乍一看对我来说很好,而不是你的观点 But I find that I can just set that header manually to "bypass" cors 我看不出有什么大问题。

    然后我从headers event.headers.origin获取原点。但我发现我可以手动设置头部“绕过”CORS。是否有可靠的方法检测源域?

    您当前使用的代码是我能想到的唯一方法,如何从我的头上检测源域。尽管如您所说,您只需手动设置头文件,并且0保证头文件是正确的或有效的。它不应该被用作安全的信任层。对于浏览器,它们限制如何设置此头(请参见 Forbidden header name )但是,如果您控制HTTP客户机(例如 curl , postman 等)您可以轻松地发送您想要的任何邮件头。没有什么技术可以阻止我向您的Web服务器发送任何具有任何值的邮件头。

    因此,归根结底,这可能不是一个巨大的担忧。如果有人篡改了这个头部,那么他们将面临安全风险和意外行为。有很多方法可以绕过CORS, like this , or this , or this 也许吧。所以在一天结束的时候,你可以绕过CORS,尽管你尽了最大努力去执行它。尽管所有这些技巧都是黑客技术,可能不会被普通用户使用。与更改原始头段相同,不太可能由普通用户完成。

    还有一些其他的技巧,你可以看看tho,试图执行它多一点。你可以查一下 refer header ,并查看它是否与原始标题相同。同样,可以为任何头发送任何内容,但会使其变得更难,并强制执行您需要的内容多一点。

    如果您假定源报头应该始终等于API网关API的域,那么您可以查看的另一件事是 event.requestContext API网关提供的对象。那个对象有 resourceId , stage , accountId , apiId 以及一些其他有趣的附加属性。您可以考虑构建一个系统,该系统还将验证这些值,并根据这些值确定API网关中的哪个API发出请求。这可能需要确保您已将每个域分隔为单独的API网关API。

    不管怎样,我看不到 事件.requestContext 可能会篡改tho,因为AWS在将事件对象传递给您之前设置了它们。它们是从AWS派生的,并且不容易被用户篡改(除非请求的整个组成发生变化)。当然,与刚刚随请求发送的头文件和AWS传递给您的头文件相比,它的防篡改性要少得多。

    当然,您可以将这些解决方案中的多个组合在一起,以创建一个更严格地实施策略的解决方案。记住,安全性是一个范围,所以在这个范围内你能走多远取决于你自己。

    我也鼓励你记住,CORS并不完全是为了隐藏互联网上的信息。我分享了一些关于如何用一个简单的后端系统或插件绕过CORS的方法,这些方法表明它并不是完全可靠的,如果有人真的想要伪造头,他们将能够做到。但当然,在一天结束的时候,你可以尽可能地让它难以实现。但这需要实现和编写大量的代码,并进行大量检查才能实现。

    你真的要问问自己目标和目标是什么。我认为这真的决定了你接下来的步骤。您可能会确定您当前的设置足够好,不需要进一步更改。您可能会确定您正在试图保护敏感数据不被发送到未经授权的源,在这种情况下,CORS可能不是一个可靠的解决方案(因为可以将该头设置为任何内容)。或者,您可能会决定您可能需要更多地将事情锁定,并使用其他一些信号来进一步实施您的策略。


    TLDR 你当然可以设置 Origin 头到任何你想要的,因此它不应该完全信任。如果您假定源报头始终等于API网关API的域,则可以尝试使用 事件.requestContext 对象获取有关API网关中API的更多信息,以获取有关请求的更多信息。你也可以看看 Refer 标题,查看是否可以将其与 起源 标题。


    更多信息:

        2
  •  -1
  •   Lucas Kauer    6 年前

    验证多个原点的唯一方法是,使用lambda读取原点头,将其与要允许的域列表进行比较,如果匹配,则将原点头的值返回给客户端,因为访问控制允许响应中的原点头。

    信息:原始头是由用户代理自动设置的头之一。所以任何人都不能通过编程或者扩展来改变。有关详细信息,请参阅 MDN .