假设我正在开发一个调用 API 服务器的移动应用程序。 API 服务器由 API 密钥保护。
首先让我们澄清开发人员中关于 API 的一个非常常见的误解......
与您的 API 服务器通信的人与物之间的区别
为了更好地理解之间的差异WHO和WHAT正在访问您的移动应用程序,让我们使用这张图片:
预期通信通道代表您的移动设备按您的预期使用,由合法用户使用,没有任何恶意,使用您的移动应用程序的未篡改版本,并直接与您的 API 服务器通信,而不会受到中间人攻击。
实际渠道可能代表几种不同的场景,例如具有恶意意图的合法用户可能正在使用您的移动应用程序的重新打包版本,黑客使用您的移动应用程序的正版,而中间人对其进行攻击以了解通信方式移动应用程序和 API 服务器之间的交互正在完成,以便能够自动攻击您的 API。许多其他场景也是可能的,但我们不会在这里一一列举。
我希望现在你可能已经知道为什么WHO和WHAT不一样,但如果不一样,一会儿就会清楚。
The WHO是移动应用程序的用户,我们可以通过多种方式对其进行身份验证、授权和识别,例如使用 OpenID Connect 或 OAUTH2 流。
OAUTH https://en.wikipedia.org/wiki/OAuth
一般来说,OAuth 代表资源所有者向客户端提供对服务器资源的“安全委托访问”。它指定了资源所有者授权第三方访问其服务器资源而无需共享其凭据的流程。 OAuth 专为与超文本传输协议 (HTTP) 配合使用而设计,本质上允许授权服务器在资源所有者的批准下向第三方客户端颁发访问令牌。然后,第三方使用访问令牌来访问资源服务器托管的受保护资源。
OpenID 连接 https://openid.net/connect/
OpenID Connect 1.0 是 OAuth 2.0 协议之上的简单身份层。它允许客户端根据授权服务器执行的身份验证来验证最终用户的身份,并以可互操作和类似 REST 的方式获取有关最终用户的基本配置文件信息。
虽然用户身份验证可能会让您的 API 服务器知道WHO正在使用 API,它不能保证请求源自WHAT您期望的,您的移动应用程序。
现在我们需要一种方法来识别WHAT正在调用您的 API 服务器,这里事情变得比大多数开发人员想象的更加棘手。这WHAT是向 API 服务器发出请求的东西。它真的是您的移动应用程序的真实实例,还是机器人、自动化脚本或攻击者使用 Postman 等工具手动侵入您的 API 服务器?
令您惊讶的是,您最终可能会发现,它可能是您的合法用户之一,使用您的移动应用程序的重新打包版本或尝试游戏化并利用您的服务的自动化脚本。
那么,要识别WHAT,开发人员倾向于使用 API 密钥,通常他们将其硬编码在移动应用程序的代码中。一些开发人员付出了额外的努力,在移动应用程序的运行时计算密钥,因此它成为运行时秘密,而不是当静态秘密嵌入到代码中时的前一种方法。
以上内容摘自我写的一篇文章,题为为什么您的移动应用程序需要 API 密钥?,并且您可以完整阅读here https://blog.approov.io/why-does-your-mobile-app-need-an-api-key,这是有关 API 密钥的系列文章中的第一篇文章。
你的问题
因此,您的问题无法通过身份验证/授权服务器来解决,无论它是否使用 Oauth、OpenID 或任何其他类型的身份验证,因为正如您现在可能已经了解的那样,该服务器只会识别WHO正在访问您的 API 服务器,而不是WHAT正在访问它。
需要澄清的是,我并不是说不应该使用这种方法,事实上使用 Oauth2/OpenID 是识别身份的最佳方法。WHO正在访问 API 服务器。
现在您可能正在思考如何解决您的问题:
我无法在移动应用程序中对 API 密钥进行硬编码,因为它可能会被盗。
好吧,你给自己买了一个头痛,没有医生或药物可以让它消失。
确实,如果您在移动应用程序中隐藏任何秘密,那么它就可以被逆向工程。在本文 https://blog.approov.io/how-to-extract-an-api-key-from-a-mobile-app-with-static-binary-analysis我写了一篇关于在移动应用程序中隐藏 API 密钥的最有效方法之一,方法是使用JNI/NDK https://developer.android.com/training/articles/perf-jni,但同时我也写了如何对其进行逆向工程:
现在是时候寻找一种更先进的技术来隐藏 API 密钥,这种方式很难从 APK 进行逆向工程,为此,我们将通过利用 JNI 使用本机 C++ 代码来存储 API 密钥在底层使用 NDK 的接口。
在我开始回答你的问题之前,我完成了下一篇文章的草稿,该文章将介绍如何执行中间人攻击来窃取 API 密钥,你将能够阅读到与此相关的内容:
虽然我们可以使用 JNI/NDK 等先进技术在移动应用程序代码中隐藏 api 密钥,但它不会阻止某人执行 MITM 攻击以窃取 api 密钥。事实上,MITM 攻击非常简单,甚至非开发人员也可以实现。
我是否告诉您,保护 API 服务器免受攻击是没有希望的?WHAT正在访问它?好吧,不,我不是……
可能的解决方案
如何保护 API 密钥?
移动应用程序应仅与您控制下的 API 服务器通信,并且对第三方 API 服务的任何访问都必须由您控制的同一 API 服务器完成。
通过这种方式,您可以将攻击面限制在一个地方,在那里您可以根据您所保护的内容的价值采用尽可能多的防御层。
根据您尝试保护的 API 密钥背后的值,您可能需要使用网络应用防火墙 https://en.wikipedia.org/wiki/Web_application_firewall(WAF),如果你能负担得起用户行为分析 https://en.wikipedia.org/wiki/User_behavior_analytics(UBA)解决方案。
WAF - Web应用程序防火墙 https://en.wikipedia.org/wiki/Web_application_firewall:
Web 应用程序防火墙(或 WAF)过滤、监视和阻止进出 Web 应用程序的 HTTP 流量。 WAF 与常规防火墙的区别在于,WAF 能够过滤特定 Web 应用程序的内容,而常规防火墙则充当服务器之间的安全门。通过检查 HTTP 流量,它可以防止源自 Web 应用程序安全缺陷的攻击,例如 SQL 注入、跨站点脚本 (XSS)、文件包含和安全错误配置。
UBA-用户行为分析 https://en.wikipedia.org/wiki/User_behavior_analytics:
Gartner 定义的用户行为分析 (UBA) 是一个关于检测内部威胁、针对性攻击和金融欺诈的网络安全流程。 UBA 解决方案着眼于人类行为模式,然后应用算法和统计分析从这些模式中检测有意义的异常,即表明潜在威胁的异常。 UBA 不跟踪设备或安全事件,而是跟踪系统的用户。 Apache Hadoop 等大数据平台正在增强 UBA 功能,允许它们分析 PB 级数据以检测内部威胁和高级持续威胁。
所有这些解决方案都基于负面识别模型,换句话说,他们尽力通过识别什么是坏的而不是什么是好来区分好坏,因此尽管使用了先进的技术,但它们很容易出现误报其中一些,如机器学习和人工智能。
因此,您可能会经常发现自己必须放松阻止对 API 服务器的访问的方式,以免影响好用户。这也意味着该解决方案需要持续监控,以验证误报不会阻止合法用户,同时正确阻止未经授权的用户。
对于为移动应用程序提供服务的 API,可以通过使用移动应用程序证明解决方案来使用肯定的识别模型,该解决方案向 API 服务器保证请求可以被信任,而不会出现误报。
移动应用程序认证
移动应用程序证明服务的作用是在运行时保证您的移动应用程序未被篡改或未在获得 root 权限的设备中运行,方法是在后台运行 SDK,该 SDK 将与云中运行的服务进行通信以证明您的移动应用程序的安全性。移动应用程序和设备运行的完整性。
成功证明移动应用程序完整性后,会发出一个短暂的 JWT 令牌,并使用只有 API 服务器和云中的移动应用程序证明服务知道的秘密进行签名。如果移动应用程序认证失败,JWT 令牌将使用 API 服务器不知道的秘密进行签名。
现在,应用程序必须在每次 API 调用时发送请求标头中的 JWT 令牌。这将允许 API 服务器仅在可以验证 JWT 令牌中的签名和过期时间时才服务请求,并在验证失败时拒绝请求。
一旦移动应用程序不知道移动应用程序证明服务使用的秘密,就不可能在运行时对其进行逆向工程,即使应用程序被篡改、在 root 设备中运行或通过正在使用的连接进行通信也是如此。中间人攻击的目标。
移动应用程序认证服务已作为 SAAS 解决方案存在,位于Approov https://www.approov.io/approov-in-detail.html(我在这里工作)为多个平台提供 SDK,包括 iOS、Android、React Native 等。集成还需要对 API 服务器代码进行少量检查,以验证云服务颁发的 JWT 令牌。此检查对于 API 服务器能够决定服务哪些请求以及拒绝哪些请求是必要的。
结论
最后,必须根据您要保护的内容的价值以及该类型数据的法律要求(例如欧洲的 GDPR 法规)来选择用于保护 API 服务器的解决方案。
因此,使用 API 密钥可能听起来像是锁上家门并将钥匙留在垫子下,但不使用它们就像将车停在门关闭的情况下,但将钥匙放在点火装置中。