API网关Lambda CORS处理程序。安全地获取原产地

时间:2018-12-19 08:26:38

标签: amazon-web-services lambda cors aws-api-gateway api-gateway

我想为多个来源实现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 个答案:

答案 0 :(得分:3)

  

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

乍看之下,您的代码对我来说看起来不错,除了您的观点But I find that I can just set that header manually to "bypass" cors以外,我看不到任何重大问题。

  

然后我从headers event.headers.origin获取起源。但是我发现我可以手动将标题设置为“绕过” cors。是否有检测来源域的可靠方法?

您当前正在使用的代码是我想到如何唯一地检测源域的唯一方法。尽管正如您所说,您可以手动设置标题,但是0保证标题正确或有效。它不应用作安全性的信任层。对于浏览器,它们限制了可以如何设置此标头(请参见Forbidden header name)。但是,如果您控制HTTP客户端(例如curlpostman等),则可以轻松地发送所需的任何标头。没有什么技术上的明智之举可以阻止我将任何具有所需值的标头发送到您的Web服务器。

因此,归根结底,这可能不是一个大问题。如果有人篡改了该标头,则他们将面临安全风险和意外行为。有很多方法可以绕开CORS,例如like thisor thisor this。因此,尽管您尽了最大努力来执行,但最终还是可以绕过CORS。尽管所有这些技巧都是骇客,但普通用户可能不会使用。与更改原始标头相同,普通用户不太可能完成。

您还可以尝试一些其他技巧来尝试进一步实施它。您可以查看refer header,看看与原始标头是否相同。同样,可以为任何标头发送任何内容,但会使它变得更难一点,并执行您想要的更多内容。

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

我仍然看不到event.requestContext中的那些值会被篡改,因为AWS在将事件对象传递给您之前已对其进行了设置。它们是从AWS派生的,用户很难轻易对其进行篡改(除非请求的整个构成发生变化)。当然,与仅随请求发送的标头相比,防篡改要少得多,并且AWS会传递给您。

当然,您可以将这些解决方案中的多个结合在一起,以创建可以进一步实施您的政策的解决方案。请记住,安全性是一个频谱,因此,您可以将频谱走多远取决于您自己。

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

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


tldr 您可以确定将Origin标头设置为所需的任何内容,因此不应完全信任它。如果您认为原始标头应始终等于API Gateway API的域,则可以尝试使用event.requestContext对象在API Gateway中获取有关API的更多信息,以获取有关请求的更多信息。您还可以查看Refer标头,看看是否可以将其与Origin标头进行比较。


更多信息:

答案 1 :(得分:-1)

验证多个来源的唯一方法是像您所做的那样,lambda读取Origin头,将其与您希望允许的域列表进行比较,如果匹配,则将Origin头的值返回到客户端作为响应中的Access-Control-Allow-Origin标头。

信息:Origin标头是由用户代理自动设置的标头之一。因此,任何人都不能以编程方式或通过扩展名进行更改。有关更多详细信息,请查看MDN