假设我正在开发一个调用API服务器的移动应用程序。 API服务器由API密钥保护。
我无法在移动应用程序内对API密钥进行硬编码,因为它可能被盗。
如何保护API密钥?
这个问题通常是如何解决的?
(听起来您要保护的API密钥是您不拥有的API服务。)
一种方法是使用认证服务器。私有API密钥保留在身份验证服务器上,并且仅在有效登录后共享。
那么这是如何工作的呢?
在架构上,您需要一个单独的身份验证服务器,它将为您提供2个不同的服务器:
第二种方法是使用传递服务器。私有API密钥永远不会在此方法中共享。可以在pass-thru服务器上添加身份验证,但不是必需的。
那么这是如何工作的呢?
在这种情况下,您拥有pass-thru服务器,因此您永远不需要共享API密钥,用户身份验证是可选的。
假设我正在开发一个调用API服务器的移动应用程序。 API服务器由API密钥保护。
让我们首先清楚开发人员对API的一个非常普遍的误解......
为了更好地理解WHO和WHAT之间的差异,访问您的移动应用程序,让我们使用这张图片:
预期通信渠道代表您的移动设备按照您的预期使用,由合法用户使用,没有任何恶意,使用未经过篡改的移动应用程序版本,并直接与您的API服务器通信,而不会受到中间人的攻击。
实际频道可能代表几种不同的场景,例如具有恶意意图的合法用户可能正在使用您的移动应用程序的重新打包版本,黑客使用您的移动应用程序的正版,而中间人攻击它以了解通信方式移动应用程序和API服务器之间正在进行,以便能够自动攻击您的API。许多其他方案都是可能的,但我们不会在此列举每一个方案。
我希望到现在为止你可能已经知道为什么WHO和WHAT不一样,但如果不是,它会在一瞬间变得清晰。
WHO是移动应用程序的用户,我们可以通过多种方式进行身份验证,授权和识别,例如使用OpenID Connect或OAUTH2流程。
通常,OAuth代表资源所有者向客户端提供对服务器资源的“安全委托访问”。它指定资源所有者授权第三方访问其服务器资源而不共享其凭据的过程。 OAuth专门设计用于超文本传输协议(HTTP),实质上允许授权服务器在资源所有者的批准下向第三方客户端发出访问令牌。然后,第三方使用访问令牌访问资源服务器托管的受保护资源。
OpenID Connect 1.0是OAuth 2.0协议之上的简单身份层。它允许客户端根据授权服务器执行的身份验证来验证最终用户的身份,以及以可互操作和类似REST的方式获取有关最终用户的基本配置文件信息。
虽然用户身份验证可能会让您的API服务器知道WHO正在使用API,但无法保证请求源自您期望的移动应用程序。
现在我们需要一种方法来识别什么是调用你的API服务器,这里的事情变得比大多数开发人员想象的更棘手。什么是向API服务器发出请求的事情。它真的是您的移动应用程序的真实实例,还是机器人,自动脚本或攻击者使用Postman等工具手动戳您的API服务器?
为了您的惊喜,您可能最终发现它可能是您的合法用户之一使用您的移动应用程序的重新打包版本或尝试游戏化并利用您的服务的自动脚本。
好吧,为了确定什么,开发人员倾向于使用API密钥,通常他们在他们的移动应用程序的代码中进行硬编码。一些开发人员在移动应用程序中更加努力地在运行时计算密钥,因此当代码中嵌入静态秘密时,它变为运行时机密,而不是前一种方法。
上面的文章是从我写的一篇文章中提取的,题为“你的移动应用程序需要什么样的API密钥?”,你可以阅读完整的here,这是关于API密钥的系列文章的第一篇文章。
因此,无论是使用Oauth,OpenID还是任何其他类型的身份验证,您的问题都无法通过身份验证/授权服务器解决,因为您现在可能已经理解,此服务器将仅识别WHO正在访问您的API服务器,而不是什么是访问它。
为了清楚起见我并不是说不应该使用这种方法,事实上使用Oauth2 / OpenID是识别WHO正在访问API服务器的最佳方法。
到现在为止,您可能会想到如何解决问题:
我无法在移动应用程序内对API密钥进行硬编码,因为它可能被盗。
好吧,你给自己买了头疼,没有医生或药可以让它消失。
确实,如果你在移动应用程序中隐藏任何秘密,那么它就可以进行逆向工程。在this article中,我写了一篇关于在移动应用程序中隐藏API密钥的最有效方法之一,使用JNI/NDK,但同时我也写了关于如何对其进行逆向工程的文章:
现在是时候寻找一种更先进的技术来隐藏API密钥,这种方式很难从APK进行逆向工程,为此我们将利用本机C ++代码来存储API密钥,方法是利用JNI在引擎盖下使用NDK的界面。
在我开始回答您的问题之前,我完成了下一篇文章的草稿,该文章将介绍如何执行中间人攻击以窃取API密钥,您将能够阅读以下内容:
虽然我们可以使用高级技术(如JNI / NDK)来隐藏移动应用程序代码中的api密钥,但它不会阻止某人执行MITM攻击以窃取API密钥。实际上,MITM攻击很容易达到非开发人员甚至可以实现的程度。
我是否告诉过你,保护API服务器没有希望从什么访问它?好吧不,我不是......
如何保护API密钥?
移动应用程序应仅与您控制的API服务器通信,并且任何对第三方API服务的访问必须由您控制的同一API服务器完成。
通过这种方式,您可以将攻击面限制在一个地方,在那里您将使用尽可能多的防御层,因为您保护的是值得的。
根据您要保护的API密钥背后的值,您可能需要使用Web Application Firewall(WAF),如果您能够负担得起User Behavior Analytics(UBA)解决方案。
WAF - Web Application Firewall:
Web应用程序防火墙(或WAF)过滤,监视和阻止与Web应用程序之间的HTTP流量。 WAF与常规防火墙的区别在于,WAF能够过滤特定Web应用程序的内容,而常规防火墙则充当服务器之间的安全门。通过检查HTTP流量,它可以防止源自Web应用程序安全漏洞的攻击,例如SQL注入,跨站点脚本(XSS),文件包含和安全性错误配置。
UBA - User Behavior Analytics:
Gartner定义的用户行为分析(UBA)是一个关于检测内部威胁,针对性攻击和财务欺诈的网络安全流程。 UBA解决方案着眼于人类行为的模式,然后应用算法和统计分析来检测那些模式中的有意义的异常 - 指示潜在威胁的异常。 UBA不是跟踪设备或安全事件,而是跟踪系统的用户。像Apache Hadoop这样的大数据平台正在增加UBA功能,允许他们分析数PB的数据来检测内部威胁和高级持续性威胁。
所有这些解决方案都基于否定识别模型工作,换句话说,他们尽力识别坏东西,而不是好东西,从而尽管使用了先进的技术,但它们很容易出现误报其中一些,如机器学习和人工智能。
因此,您可能会发现自己不得不放松阻止访问API服务器的方式,以免影响好用户。这也意味着此解决方案需要持续监控,以验证误报不会阻止您的合法用户,同时他们正确地阻止未经授权的用户。
关于为移动应用程序提供服务的API,可以使用移动应用程序证明解决方案来使用正面识别模型,该解决方案向API服务器保证可以信任请求而不会出现误报。
移动应用证明服务的作用是在运行时保证您的移动应用未被篡改或未在根设备中运行,方法是在后台运行SDK,该SDK将与云中运行的服务进行通信以证明正在运行移动应用和设备的完整性。
在成功证明移动应用程序完整性时,会发布短时间JWT令牌,并使用只有API服务器和云中的移动App证明服务才知道的秘密进行签名。在移动应用证明失败的情况下,JWT令牌使用API服务器不知道的秘密进行签名。
现在,应用程序必须在每次API调用时发送请求标头中的JWT令牌。这将允许API服务器仅在可以验证JWT令牌中的签名和到期时间时提供请求,并在验证失败时拒绝它们。
一旦移动应用程序不知道移动应用证明服务使用的秘密,即使应用程序被篡改,在有根设备中运行或通过正在进行的连接进行通信,也无法在运行时对其进行反向工程。中间人攻击的目标。
移动应用证明服务已作为SAAS解决方案存在于Approov(我在这里工作),该解决方案为多个平台提供SDK,包括iOS,Android,React Native等。集成还需要对API服务器代码进行少量检查,以验证云服务发出的JWT令牌。此检查对于API服务器能够决定要提供哪些请求以及拒绝哪些请求是必要的。
最后,必须根据您要保护的内容的价值以及该类型数据的法律要求(例如欧洲的GDPR法规)选择用于保护API服务器的解决方案。
所以使用API键可能听起来像锁住你家的门并把钥匙留在垫子下面,但不使用它们喜欢让你的车停在车门关闭的地方,但钥匙在点火时。
由于您实际上需要API密钥来访问后端服务器,但无法将API密钥存储在设备上,我实际上只能看到一种可能的方法。
构建一个中间Mobile API,然后调用Backend服务器API。让您的移动应用程序调用中间Mobile API。此移动API应仅允许移动应用程序所需的特定调用,并且仅返回移动应用程序所需的数据。
为避免将中间移动API暴露给任何外部方,您应该要求某种身份验证。另外,请确保通过https提供中间移动API。为了进一步提高安全性,您可以考虑使用证书。
(您可以使用格式强大的算法加密Backend API的API密钥并存储在设备上,以避免它易于检索,但是有一些嗅探工具可以让您嗅探从移动设备发出的流量,即使是在https上也是如此,所以这不是一个安全的选择。)
可以说,存储在客户端应用程序中的任何秘密都是易受攻击的。存储在清单中或嵌入代码中的秘密很容易提取。混淆和应用程序强化可能会使这更加困难。在安全文件或密钥库中存储秘密更好,但仍然永远不会完全安全。如果这个秘密足够有价值,它可能会被盗。
从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。如果你想看看如何从你的应用程序中完全删除秘密(需要第三方演示库),你可以通过https://hackernoon.com/hands-on-mobile-api-security-get-rid-of-client-secrets-a79f111b6844工作。