【问题标题】:API Gateway Lambda CORS handler. Getting Origin securelyAPI Gateway Lambda CORS 处理程序。安全获取 Origin
【发布时间】:2019-05-19 16:59:08
【问题描述】:

我想为多个来源实现 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。是否有可靠的方法来检测源域?

【问题讨论】:

  • 听起来推荐的方法是让您的服务器从客户端读取 Origin 标头,将其与您希望允许的域列表进行比较,如果匹配,则回显该值将Origin 标头作为响应中的Access-Control-Allow-Origin 标头返回给客户端。
  • 刚刚发布了一个答案。如果您提供有关您的目标的更多背景信息以及有关您期望corsUrls 等于什么以及您期望requestOrigin 是什么的更多信息,我可以进一步完善我的答案,以针对您的确切情况提供更具体的细节。我很好奇你的目标和目标是什么。这将真正有助于确定适合您需求的解决方案。

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


【解决方案1】:

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

乍一看,您的代码看起来不错,除了您的观点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 标头进行比较。


更多信息:

【讨论】:

    【解决方案2】:

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

    信息:Origin 标头是由用户代理自动设置的标头之一。因此任何人都无法通过编程或扩展进行更改。更多详情,请查看MDN

    【讨论】:

    • 重要的是要注意,归根结底,任何人都可以将源头设置为他们想要的任何东西,因此不应完全依赖于作为防御策略。
    • 按照 MDN 中的规定,您不能更改此标头。看这里:developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Origin
    • 我实际上已经asked this question before。现实情况是任何人都可以向服务器发送任何 HTTP 请求。仅仅因为它是 BROWSERS 的受保护标头并不意味着您应该自动信任它。我可以使用 Postman 之类的工具或构建自定义 HTTP 库来发送我想要的任何标题或内容。无法保证我发送给您的信息是正确的。你听起来好像有某种类型的保证源头总是正确的。
    • 这不是我的意思……我的意思是,浏览器发出的请求不允许您更改标题。但感谢您补充回复。
    猜你喜欢
    • 2019-04-21
    • 2016-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-19
    • 1970-01-01
    • 2018-12-06
    • 2016-05-13
    相关资源
    最近更新 更多