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