移动后端 API 密钥的安全性
Security of Mobile Backend API key
假设我正在开发一个调用 API 服务器的移动应用程序。 API 服务器由 API 密钥保护。
我无法在移动应用程序中对 API 密钥进行硬编码,因为它可能被盗。
如何保护 API 密钥?
由于您实际上需要API密钥来访问后端服务器,但无法将API密钥存储在设备上,所以我真的只能看到一种可能的方法。
构建一个中间 Mobile API,后者又调用后端服务器 API。让您的移动应用程序调用中间 Mobile API。此手机 API 应仅允许移动应用所需的特定调用,并且仅 return 移动应用所需的数据。
为避免将您的中间手机 API 暴露给任何外部方,您应该需要某种身份验证。
此外,请确保您的中级移动设备 API 是通过 https 提供服务的。
为了进一步提高安全性,您可以考虑使用证书。
(您可以使用强大的加密算法为后端 API 加密您的 API 密钥并存储在设备上以避免它被轻易检索,但是有可用的嗅探工具可以让您嗅探从移动设备传出的流量,即使是在 https 上,所以这不是一个安全的选择。)
How is that problem usually solved?
(听起来您试图保护的 API-key 是针对您不拥有的 API 服务的。)
一种方法是使用身份验证服务器。私钥 API-key 保存在身份验证服务器上,仅在有效登录后共享。
那么这是如何工作的?
- 移动客户端用户输入登录名和密码
- 这些凭据被发送到身份验证服务器并在那里进行验证
- 如果登录有效,API-密钥被发送到移动客户端
在架构上,您需要一个单独的身份验证服务器,这会给您留下 2 个不同的服务器:
一些 API-key 服务器,您需要一个私人 API-key 才能使用
认证服务器(用于验证用户登录和交换私钥API-keys)
第二种方法是使用直通服务器。私有 API-key 永远不会在这种方法中共享。可以在直通服务器上添加身份验证,但不是必需的。
那么这是如何工作的?
- 移动用户联系直通服务器以获取来自 API
的数据
- 直通服务器进行 api 调用(使用存储的私有 API-key)
- API 服务器用数据响应直通服务器
- 直通服务器将 API 响应转发到移动应用程序
在这种情况下,您拥有直通服务器,因此您永远不需要共享您的 API 密钥,并且用户身份验证是可选的。
Suppose I am developing a mobile application that makes calls to an API server. The API server is secured by an API Key.
让我们首先澄清开发人员中关于 APIs...
的一个非常普遍的误解
与您的 API 服务器进行通信的人员和内容之间的差异
为了更好地理解 WHO 和 WHAT 访问您的移动应用程序的区别,让我们使用这张图片:
预期的通信渠道表示您的手机正按您的预期使用,由合法用户使用,没有任何恶意,使用您的移动应用程序的未篡改版本,并且直接与您的 API 服务器通信而不是人为中间被攻击了
实际的渠道可能代表几种不同的情况,比如一个怀有恶意的合法用户可能正在使用你的移动应用程序的重新打包版本,一个黑客使用你的移动应用程序的正版,同时中间人攻击它了解移动应用程序和 API 服务器之间的通信是如何进行的,以便能够自动攻击您的 API。还有很多其他可能的情况,但我们不会在这里一一列举。
我希望现在您可能已经知道为什么 WHO 和 WHAT 不一样,但如果不一样一会儿就清楚了。
WHO 是移动应用程序的用户,我们可以通过多种方式对其进行身份验证、授权和识别,例如使用 OpenID Connect 或 OAUTH2 流程。
Generally, OAuth provides to clients a "secure delegated access" to server resources on behalf of a resource owner. It specifies a process for resource owners to authorize third-party access to their server resources without sharing their credentials. Designed specifically to work with Hypertext Transfer Protocol (HTTP), OAuth essentially allows access tokens to be issued to third-party clients by an authorization server, with the approval of the resource owner. The third party then uses the access token to access the protected resources hosted by the resource server.
OpenID Connect 1.0 is a simple identity layer on top of the OAuth 2.0 protocol. It allows Clients to verify the identity of the End-User based on the authentication performed by an Authorization Server, as well as to obtain basic profile information about the End-User in an interoperable and REST-like manner.
虽然用户身份验证可能会让您的 API 服务器知道 WHO 正在使用 API,但它不能保证请求来自 你期待什么,你的移动应用程序。
现在我们需要一种方法来识别什么 正在调用您的API 服务器,这里事情变得比大多数开发人员想象的更棘手。 WHAT 是向 API 服务器发出请求的东西。它真的是您的移动应用程序的真实实例,还是机器人、自动脚本或攻击者使用 Postman 等工具手动浏览您的 API 服务器?
令您惊讶的是,您最终可能会发现它可能是您的合法用户之一,使用您的移动应用程序的重新打包版本或试图游戏化并利用您的服务的自动脚本。
好吧,为了识别 WHAT,开发人员倾向于求助于 API 键,通常他们会在其移动应用程序代码中 hard-code 。一些开发人员更加努力地在移动应用程序中计算 run-time 处的密钥,因此它成为一个运行时秘密,而不是前一种在代码中嵌入静态秘密的方法。
以上write-up摘自我写的一篇文章,标题为WHY DOES YOUR MOBILE APP NEED AN API KEY?,你可以完整阅读 here,这是关于 API 键的系列文章中的第一篇。
你的问题
所以你的问题无法用 authentication/authorizaion 服务器解决,无论它是否使用 Oauth、OpenID 或任何其他类型的身份验证,因为你现在可能很清楚,该服务器将只识别 WHO 正在访问您的 API 服务器,而不是 WHAT 正在访问它。
需要说明的是,我并不是说不应该使用这种方法,实际上使用 Oauth2/OpenID 是识别 WHO 正在访问的最佳方法API 服务器。
现在您可能正在思考如何解决您的问题:
I cannot hard-code the API Key inside the mobile application because it can be stolen.
好吧,你已经让自己头疼了,没有医生或药物可以让它消失。
的确,如果您在移动应用程序中隐藏了任何秘密,那么它就可以被逆向工程。在 this article I wrote about one of the most effective ways to hide an API key in a mobile app, by using JNI/NDK 中,但同时我也写了如何对其进行逆向工程:
It's time to look for a more advanced technique to hide the API key in a way that will be very hard to reverse engineer from the APK, and for this we will make use of native C++ code to store the API key, by leveraging the JNI interface which uses NDK under the hood.
在我开始回答你的问题之前,我完成了下一篇文章的草稿,那将是关于如何执行中间人攻击来窃取 API 密钥,你将能够阅读相关内容:
While we can use advanced techniques, like JNI/NDK, to hide the api key in the mobile app code it will not impede someone from performing a MITM attack in order to steal the api key. In fact a MITM attack is easy to the point that can even be achieved by non developers.
我是不是告诉你,保护 API 服务器免受 WHAT 访问它没有希望?好吧,不,我不是...
可能的解决方案
How can I protect the API key?
移动应用程序只能与您控制的 API 服务器通信,任何对第三方 API 服务的访问都必须由您控制的同一 API 服务器完成控制。
通过这种方式,您可以将攻击面限制在一个地方,在那里您可以根据所保护的内容采用尽可能多的防御层。
根据您要保护的 API 密钥背后的价值,您可能需要使用 Web Application Firewall(WAF), and if you can afford it a User Behavior Analytics(UBA) 解决方案。
WAF - Web Application Firewall:
A web application firewall (or WAF) filters, monitors, and blocks HTTP traffic to and from a web application. A WAF is differentiated from a regular firewall in that a WAF is able to filter the content of specific web applications while regular firewalls serve as a safety gate between servers. By inspecting HTTP traffic, it can prevent attacks stemming from web application security flaws, such as SQL injection, cross-site scripting (XSS), file inclusion, and security misconfigurations.
UBA - User Behavior Analytics:
User behavior analytics (UBA) as defined by Gartner is a cybersecurity process about detection of insider threats, targeted attacks, and financial fraud. UBA solutions look at patterns of human behavior, and then apply algorithms and statistical analysis to detect meaningful anomalies from those patterns—anomalies that indicate potential threats. Instead of tracking devices or security events, UBA tracks a system's users. Big data platforms like Apache Hadoop are increasing UBA functionality by allowing them to analyze petabytes worth of data to detect insider threats and advanced persistent threats.
所有这些解决方案都基于负面识别模型,换句话说,它们会尽力区分好坏y 识别什么是坏的,而不是什么是好的,因此他们很容易出现误报,尽管他们中的一些人使用了先进的技术,比如机器学习和人工智能。
因此,您可能经常发现自己不得不放松阻止对 API 服务器的访问,以免影响好的用户。这也意味着此解决方案需要持续监控,以验证误报不会阻止您的合法用户,同时它们会适当地阻止未经授权的用户。
关于 API 为移动应用程序提供服务的积极识别模型可以通过使用移动应用程序证明解决方案来使用,该解决方案向 API 服务器保证请求可以被信任而没有虚假的可能性正面。
移动应用认证
移动应用证明服务的作用是在 run-time 保证您的移动应用未被篡改或未被 运行 在已获得 root 权限的设备中被 运行 中的 SDK将与云中的服务 运行 通信以证明移动应用程序和设备的完整性的后台已 运行 开启。
在成功证明移动应用程序完整性后,将发布一个短期 JWT 令牌并使用只有 API 服务器和云中的移动应用程序证明服务知道的秘密进行签名。如果移动应用证明失败,JWT 令牌将使用 API 服务器不知道的秘密进行签名。
现在,应用程序必须在每次 API 调用请求的 headers 中发送 JWT 令牌。这将允许 API 服务器仅在可以验证 JWT 令牌中的签名和过期时间时才为请求提供服务,并在验证失败时拒绝请求。
一旦移动应用程序不知道移动应用程序证明服务使用的秘密,即使应用程序被篡改,也无法在 run-time 对其进行逆向工程,运行 root 设备或通过成为中间人攻击目标的连接进行通信。
Approov(我在这里工作),移动应用证明服务已经作为 SAAS 解决方案存在,它为多个平台提供 SDK,包括 iOS、Android、React Native 和其他。集成还需要在 API 服务器代码中进行少量检查,以验证云服务发布的 JWT 令牌。此检查对于 API 服务器能够决定处理哪些请求以及拒绝哪些请求是必要的。
结论
最后,为了保护您的 API 服务器,必须根据您要保护的内容的价值以及该类型数据的法律要求来选择解决方案,例如欧洲的 GDPR 法规。
所以使用 API 钥匙听起来像是锁上家门并将钥匙放在垫子下面,但不使用它们就像把车停在车门关着一样,但钥匙在点火。
可以公平地说,存储在客户端应用程序中的任何秘密都容易受到攻击。存储在清单中或嵌入代码中的秘密很容易提取。混淆和应用程序强化会使这变得更加困难。将秘密存储在安全文件或密钥库中更好,但仍然永远不会完全安全。如果这个秘密足够有价值,它是可以被窃取的。
以 API 密钥开始并通过 OAuth2 工作的移动 API 安全概述位于 https://hackernoon.com/mobile-api-security-techniques-682a5da4fe10。
OAuth2 有多个流程,具体取决于您的要求。最常见的流程,授权代码授予,同时使用客户端身份验证(认为 API 密钥)和用户身份验证。如果您只需要客户端身份验证,则可以使用更简单的客户端凭据流程。 AppAuth 是适用于 iOS 和 Android 的 OAuth 框架。我在 https://hackernoon.com/adding-oauth2-to-mobile-android-and-ios-clients-using-the-appauth-sdk-f8562f90ecff.
发布了 AppAuth 的 Android 演练
有关如何在 Android 应用程序中泄露机密的演练,请查看 https://github.com/approov/shipfast-api-protection. And if you want to see how to remove secrets from your app altogether (requires 3rd party demo library), you can work through https://hackernoon.com/hands-on-mobile-api-security-get-rid-of-client-secrets-a79f111b6844。
假设我正在开发一个调用 API 服务器的移动应用程序。 API 服务器由 API 密钥保护。
我无法在移动应用程序中对 API 密钥进行硬编码,因为它可能被盗。
如何保护 API 密钥?
由于您实际上需要API密钥来访问后端服务器,但无法将API密钥存储在设备上,所以我真的只能看到一种可能的方法。
构建一个中间 Mobile API,后者又调用后端服务器 API。让您的移动应用程序调用中间 Mobile API。此手机 API 应仅允许移动应用所需的特定调用,并且仅 return 移动应用所需的数据。
为避免将您的中间手机 API 暴露给任何外部方,您应该需要某种身份验证。 此外,请确保您的中级移动设备 API 是通过 https 提供服务的。 为了进一步提高安全性,您可以考虑使用证书。
(您可以使用强大的加密算法为后端 API 加密您的 API 密钥并存储在设备上以避免它被轻易检索,但是有可用的嗅探工具可以让您嗅探从移动设备传出的流量,即使是在 https 上,所以这不是一个安全的选择。)
How is that problem usually solved?
(听起来您试图保护的 API-key 是针对您不拥有的 API 服务的。)
一种方法是使用身份验证服务器。私钥 API-key 保存在身份验证服务器上,仅在有效登录后共享。
那么这是如何工作的?
- 移动客户端用户输入登录名和密码
- 这些凭据被发送到身份验证服务器并在那里进行验证
- 如果登录有效,API-密钥被发送到移动客户端
在架构上,您需要一个单独的身份验证服务器,这会给您留下 2 个不同的服务器:
一些 API-key 服务器,您需要一个私人 API-key 才能使用
认证服务器(用于验证用户登录和交换私钥API-keys)
第二种方法是使用直通服务器。私有 API-key 永远不会在这种方法中共享。可以在直通服务器上添加身份验证,但不是必需的。
那么这是如何工作的?
- 移动用户联系直通服务器以获取来自 API 的数据
- 直通服务器进行 api 调用(使用存储的私有 API-key)
- API 服务器用数据响应直通服务器
- 直通服务器将 API 响应转发到移动应用程序
在这种情况下,您拥有直通服务器,因此您永远不需要共享您的 API 密钥,并且用户身份验证是可选的。
Suppose I am developing a mobile application that makes calls to an API server. The API server is secured by an API Key.
让我们首先澄清开发人员中关于 APIs...
的一个非常普遍的误解与您的 API 服务器进行通信的人员和内容之间的差异
为了更好地理解 WHO 和 WHAT 访问您的移动应用程序的区别,让我们使用这张图片:
预期的通信渠道表示您的手机正按您的预期使用,由合法用户使用,没有任何恶意,使用您的移动应用程序的未篡改版本,并且直接与您的 API 服务器通信而不是人为中间被攻击了
实际的渠道可能代表几种不同的情况,比如一个怀有恶意的合法用户可能正在使用你的移动应用程序的重新打包版本,一个黑客使用你的移动应用程序的正版,同时中间人攻击它了解移动应用程序和 API 服务器之间的通信是如何进行的,以便能够自动攻击您的 API。还有很多其他可能的情况,但我们不会在这里一一列举。
我希望现在您可能已经知道为什么 WHO 和 WHAT 不一样,但如果不一样一会儿就清楚了。
WHO 是移动应用程序的用户,我们可以通过多种方式对其进行身份验证、授权和识别,例如使用 OpenID Connect 或 OAUTH2 流程。
Generally, OAuth provides to clients a "secure delegated access" to server resources on behalf of a resource owner. It specifies a process for resource owners to authorize third-party access to their server resources without sharing their credentials. Designed specifically to work with Hypertext Transfer Protocol (HTTP), OAuth essentially allows access tokens to be issued to third-party clients by an authorization server, with the approval of the resource owner. The third party then uses the access token to access the protected resources hosted by the resource server.
OpenID Connect 1.0 is a simple identity layer on top of the OAuth 2.0 protocol. It allows Clients to verify the identity of the End-User based on the authentication performed by an Authorization Server, as well as to obtain basic profile information about the End-User in an interoperable and REST-like manner.
虽然用户身份验证可能会让您的 API 服务器知道 WHO 正在使用 API,但它不能保证请求来自 你期待什么,你的移动应用程序。
现在我们需要一种方法来识别什么 正在调用您的API 服务器,这里事情变得比大多数开发人员想象的更棘手。 WHAT 是向 API 服务器发出请求的东西。它真的是您的移动应用程序的真实实例,还是机器人、自动脚本或攻击者使用 Postman 等工具手动浏览您的 API 服务器?
令您惊讶的是,您最终可能会发现它可能是您的合法用户之一,使用您的移动应用程序的重新打包版本或试图游戏化并利用您的服务的自动脚本。
好吧,为了识别 WHAT,开发人员倾向于求助于 API 键,通常他们会在其移动应用程序代码中 hard-code 。一些开发人员更加努力地在移动应用程序中计算 run-time 处的密钥,因此它成为一个运行时秘密,而不是前一种在代码中嵌入静态秘密的方法。
以上write-up摘自我写的一篇文章,标题为WHY DOES YOUR MOBILE APP NEED AN API KEY?,你可以完整阅读 here,这是关于 API 键的系列文章中的第一篇。
你的问题
所以你的问题无法用 authentication/authorizaion 服务器解决,无论它是否使用 Oauth、OpenID 或任何其他类型的身份验证,因为你现在可能很清楚,该服务器将只识别 WHO 正在访问您的 API 服务器,而不是 WHAT 正在访问它。
需要说明的是,我并不是说不应该使用这种方法,实际上使用 Oauth2/OpenID 是识别 WHO 正在访问的最佳方法API 服务器。
现在您可能正在思考如何解决您的问题:
I cannot hard-code the API Key inside the mobile application because it can be stolen.
好吧,你已经让自己头疼了,没有医生或药物可以让它消失。
的确,如果您在移动应用程序中隐藏了任何秘密,那么它就可以被逆向工程。在 this article I wrote about one of the most effective ways to hide an API key in a mobile app, by using JNI/NDK 中,但同时我也写了如何对其进行逆向工程:
It's time to look for a more advanced technique to hide the API key in a way that will be very hard to reverse engineer from the APK, and for this we will make use of native C++ code to store the API key, by leveraging the JNI interface which uses NDK under the hood.
在我开始回答你的问题之前,我完成了下一篇文章的草稿,那将是关于如何执行中间人攻击来窃取 API 密钥,你将能够阅读相关内容:
While we can use advanced techniques, like JNI/NDK, to hide the api key in the mobile app code it will not impede someone from performing a MITM attack in order to steal the api key. In fact a MITM attack is easy to the point that can even be achieved by non developers.
我是不是告诉你,保护 API 服务器免受 WHAT 访问它没有希望?好吧,不,我不是...
可能的解决方案
How can I protect the API key?
移动应用程序只能与您控制的 API 服务器通信,任何对第三方 API 服务的访问都必须由您控制的同一 API 服务器完成控制。
通过这种方式,您可以将攻击面限制在一个地方,在那里您可以根据所保护的内容采用尽可能多的防御层。
根据您要保护的 API 密钥背后的价值,您可能需要使用 Web Application Firewall(WAF), and if you can afford it a User Behavior Analytics(UBA) 解决方案。
WAF - Web Application Firewall:
A web application firewall (or WAF) filters, monitors, and blocks HTTP traffic to and from a web application. A WAF is differentiated from a regular firewall in that a WAF is able to filter the content of specific web applications while regular firewalls serve as a safety gate between servers. By inspecting HTTP traffic, it can prevent attacks stemming from web application security flaws, such as SQL injection, cross-site scripting (XSS), file inclusion, and security misconfigurations.
UBA - User Behavior Analytics:
User behavior analytics (UBA) as defined by Gartner is a cybersecurity process about detection of insider threats, targeted attacks, and financial fraud. UBA solutions look at patterns of human behavior, and then apply algorithms and statistical analysis to detect meaningful anomalies from those patterns—anomalies that indicate potential threats. Instead of tracking devices or security events, UBA tracks a system's users. Big data platforms like Apache Hadoop are increasing UBA functionality by allowing them to analyze petabytes worth of data to detect insider threats and advanced persistent threats.
所有这些解决方案都基于负面识别模型,换句话说,它们会尽力区分好坏y 识别什么是坏的,而不是什么是好的,因此他们很容易出现误报,尽管他们中的一些人使用了先进的技术,比如机器学习和人工智能。
因此,您可能经常发现自己不得不放松阻止对 API 服务器的访问,以免影响好的用户。这也意味着此解决方案需要持续监控,以验证误报不会阻止您的合法用户,同时它们会适当地阻止未经授权的用户。
关于 API 为移动应用程序提供服务的积极识别模型可以通过使用移动应用程序证明解决方案来使用,该解决方案向 API 服务器保证请求可以被信任而没有虚假的可能性正面。
移动应用认证
移动应用证明服务的作用是在 run-time 保证您的移动应用未被篡改或未被 运行 在已获得 root 权限的设备中被 运行 中的 SDK将与云中的服务 运行 通信以证明移动应用程序和设备的完整性的后台已 运行 开启。
在成功证明移动应用程序完整性后,将发布一个短期 JWT 令牌并使用只有 API 服务器和云中的移动应用程序证明服务知道的秘密进行签名。如果移动应用证明失败,JWT 令牌将使用 API 服务器不知道的秘密进行签名。
现在,应用程序必须在每次 API 调用请求的 headers 中发送 JWT 令牌。这将允许 API 服务器仅在可以验证 JWT 令牌中的签名和过期时间时才为请求提供服务,并在验证失败时拒绝请求。
一旦移动应用程序不知道移动应用程序证明服务使用的秘密,即使应用程序被篡改,也无法在 run-time 对其进行逆向工程,运行 root 设备或通过成为中间人攻击目标的连接进行通信。
Approov(我在这里工作),移动应用证明服务已经作为 SAAS 解决方案存在,它为多个平台提供 SDK,包括 iOS、Android、React Native 和其他。集成还需要在 API 服务器代码中进行少量检查,以验证云服务发布的 JWT 令牌。此检查对于 API 服务器能够决定处理哪些请求以及拒绝哪些请求是必要的。
结论
最后,为了保护您的 API 服务器,必须根据您要保护的内容的价值以及该类型数据的法律要求来选择解决方案,例如欧洲的 GDPR 法规。
所以使用 API 钥匙听起来像是锁上家门并将钥匙放在垫子下面,但不使用它们就像把车停在车门关着一样,但钥匙在点火。
可以公平地说,存储在客户端应用程序中的任何秘密都容易受到攻击。存储在清单中或嵌入代码中的秘密很容易提取。混淆和应用程序强化会使这变得更加困难。将秘密存储在安全文件或密钥库中更好,但仍然永远不会完全安全。如果这个秘密足够有价值,它是可以被窃取的。
以 API 密钥开始并通过 OAuth2 工作的移动 API 安全概述位于 https://hackernoon.com/mobile-api-security-techniques-682a5da4fe10。
OAuth2 有多个流程,具体取决于您的要求。最常见的流程,授权代码授予,同时使用客户端身份验证(认为 API 密钥)和用户身份验证。如果您只需要客户端身份验证,则可以使用更简单的客户端凭据流程。 AppAuth 是适用于 iOS 和 Android 的 OAuth 框架。我在 https://hackernoon.com/adding-oauth2-to-mobile-android-and-ios-clients-using-the-appauth-sdk-f8562f90ecff.
发布了 AppAuth 的 Android 演练有关如何在 Android 应用程序中泄露机密的演练,请查看 https://github.com/approov/shipfast-api-protection. And if you want to see how to remove secrets from your app altogether (requires 3rd party demo library), you can work through https://hackernoon.com/hands-on-mobile-api-security-get-rid-of-client-secrets-a79f111b6844。