【发布时间】:2020-02-09 06:09:19
【问题描述】:
如果我在公共互联网上发布 API,但它仅供我的应用程序使用,我可以创建一个接受域的白名单,这样其他域就不能使用它。
但我总是想知道,当向我的 API 发出 HTTP 请求时,黑客不能编辑他们的“来自域”吗?难道他们不能模仿其他域来欺骗我的 API,让他们相信他们吗?
【问题讨论】:
标签: api security websecurity
如果我在公共互联网上发布 API,但它仅供我的应用程序使用,我可以创建一个接受域的白名单,这样其他域就不能使用它。
但我总是想知道,当向我的 API 发出 HTTP 请求时,黑客不能编辑他们的“来自域”吗?难道他们不能模仿其他域来欺骗我的 API,让他们相信他们吗?
【问题讨论】:
标签: api security websecurity
但我总是想知道,当向我的 API 发出 HTTP 请求时,黑客不能编辑他们的“来自域”吗?
您指的是Origin,根据Fetch Standard不应出现在所有请求中:
3. HTTP extensions
3.1. `Origin` header
The `Origin` request header indicates where a fetch originates from.
The `Origin` header is a version of the `Referer` [sic] header that does not reveal a path.
It is used for all HTTP fetches whose request’s response tainting is "cors", as well as those where request’s method is neither `GET` nor `HEAD`.
Due to compatibility constraints it is not included in all fetches.
让我们测试一下:
$ curl http://httpbin.org/headers
{
"headers": {
"Accept": "*/*",
"Host": "httpbin.org",
"User-Agent": "curl/7.58.0",
"X-Amzn-Trace-Id": "Root=1-5e907f49-3b96ed48ef957ff4c8aa435e"
}
}
如您所见,cURL 正确实现了 RFC,并且不会为 GET 请求发送 Origin 标头。
因此,即使攻击者无法欺骗它(就像他们可以轻松做到的那样),您也不能依赖它,因为任何能够正确实施 RFC 的浏览器都会被您的 API 列入黑名单,除非您的 API 仅由以下人员访问始终实现Origin 标头的非浏览器客户端,无论哪种http 方法。
他们不能模仿其他域来欺骗我的 API 以使他们信任他们吗?
攻击者可以看到您的正版应用如何处理请求并使用正确的Origin 标头重放它:
$ curl http://httpbin.org/headers -H "Origin: your-genuine.domain.com"
{
"headers": {
"Accept": "*/*",
"Host": "httpbin.org",
"Origin": "your-genuine.domain.com",
"User-Agent": "curl/7.58.0",
"X-Amzn-Trace-Id": "Root=1-5e907f9a-4696e1c9ec807a0defdeca54"
}
}
了解使用您的应用的真实域重播请求是多么容易;)。您可以在我为问题How to secure REST API from replay attacks with parameter manipulation? 给出的other answer 中阅读有关重放攻击的更多信息。
因此尝试基于Origin 标头保护您的 API 是不可行的,因为首先 RFC 不允许在所有请求方法中发送它,其次是伪造它非常简单。
如果我在公共互联网上发布 API,但它仅供我的应用程序使用,我可以创建一个接受域的白名单,这样其他域就不能使用它。
正如上面已经证明的那样,依赖域来执行请求是不可行的。
所以现在您可能想知道如何保护您的 API 服务器不被未经授权的客户端使用?
该方法将取决于您的 API 服务器应该提供什么服务,仅限 Web 应用程序,仅限移动应用程序,两者,甚至可能是 IOT 客户端?
为了让您了解如何开始应用防御层,您需要首先了解 谁 与 什么 访问您的 API 服务器之间的区别。您可以去阅读this article 部分以找到以下声明:
what 是向 API 服务器发出请求的事物。它真的是您的移动应用程序的真实实例,还是机器人、自动脚本或攻击者使用 Postman 之类的工具手动绕过您的 API 服务器?
谁是移动应用的用户,我们可以通过多种方式进行身份验证、授权和识别,例如使用 OpenID Connect 或 OAUTH2 流。
如果上面两句话还不够清楚,那就花几秒钟阅读链接文章中的整个部分。
既然您了解了 谁 和 什么 访问您的 API 服务器之间的区别,您就可以开始应用尽可能多的防御层了,因为您可以负担得起并且是法律要求的。
对于仅服务于移动应用的 API,您最终会希望采用这种类型的架构:
是的,没有 API 密钥或任何其他类型的机密存储在移动应用程序中,您可以在我为问题 How to secure an API REST for mobile app? (if sniffing requests gives you the “key”) 给出的这个other answer 中阅读更多信息,该图更详细地解释了该图形。
对于 Web 应用程序,如果您已经阅读了关于重放攻击答案的上一个链接,您可能已经被覆盖,但如果没有,这里又是 the link 我为问题 How to secure REST API from replay attacks with parameter manipulation? 提供的。此答案作为使用 HMAC 对发送到 API 服务器的请求进行签名的代码示例。
如果没有我通常推荐的访问 OWASP 基金会的优秀作品,我无法完成安全答案:
The Web Security Testing Guide:
OWASP Web 安全测试指南包括用户可以在自己的组织中实施的“最佳实践”渗透测试框架和描述测试最常见 Web 应用程序和 Web 服务安全问题的技术的“低级”渗透测试指南。
The Mobile Security Testing Guide:
移动安全测试指南 (MSTG) 是一本用于移动应用安全开发、测试和逆向工程的综合手册。
【讨论】:
并非每个 HTTP 请求都指定其域,因此您最多可以尝试将源 IP 映射到域。
如果您接受的域具有恒定的 IP 范围,您可以将它们列入白名单并阻止其他所有内容。
如果攻击者在通向您的主机站点的网络层中有内部人员,则通常可以进行 IP 欺骗。没有它,攻击者可以尝试对您的 API 进行 DoS,但他们需要 a lot of work 才能发送 HTTP 请求。
如果您使用 HTTP 标头来声明域,那么攻击者绝对可以欺骗它们。
如果您的 API 仅服务于您的应用程序,最简单的解决方案是使用 HTTPS 并对每个请求进行签名和/或身份验证(查看 JWT,这几天非常流行)。
还有一些基于识别“意外”请求的解决方案,这些解决方案也不需要您的应用具有恒定的 IP 范围,并且向不属于您的应用开放 API 也更安全。这些是Web Application Firewall (WAF) solutions,有些有免费套餐。
要记住的关键是,有大量的“基础”黑客和少量的“大师”黑客,而安全就是从这个金字塔的较低层清除尽可能多的黑客。一个强大、足智多谋、资金充足的攻击者最终会攻击您,但更多情况下,您只是希望那些想赚钱的攻击者去攻击更容易的目标。
【讨论】:
HMAC-SHA256(base64urlEncoding(header) + '.' + base64urlEncoding(payload), secret )。 SHA256 是一种快速算法,当黑客发现他可以使用任何帐户时,每秒可以在中等 GPU 上暴力破解数百万次哈希以找到secret。当从盐中添加至少 40 - 50 个好的随机(utf8)字符时,sha256 可能是“安全的”。但是,当您使用 bcrypt/blowfish en.wikipedia.org/wiki/Blowfish_(cipher) 作为签名或使用 RSA offcource 时,JWT 会更安全。