[关闭]
@liuhui0803 2017-11-15T15:06:03.000000Z 字数 3770 阅读 6561

SafetyNet Attestation API的十大常见使用误区

开发 安全 Android SafetyNet API


摘要:

本文介绍了Android开发者在自己的应用中使用SafetyNet Attestation API验证设备完整性过程中需要注意的十大问题。

正文:

SafetyNet Attestation API可以帮助我们评估运行应用的Android环境的安全性与兼容性。自从2015年3月发布后,很多开发者已经将其成功集成在自己的Android应用中,进而根据运行自己应用的设备完整性和兼容性做出更多合理的决策。

几年来,SafetyNet Attestation API也在不断完善,使用率稳步增长。然而与任何安全/反滥用相关的API一样,围绕SafetyNet有很多常见误区会导致开发者开发的系统不够稳定,甚至产生虚假的安全感。

本文将介绍开发者在给自己的应用集成SafetyNet Attestation API时最常见的十大误区。

1. 未获取API key

与Google的其他很多API类似,SafetyNet Attestation API需要具备API key才能正常使用。此外SafetyNet Attestation API每个Key还有用量限制。虽然这个限制可以增加,但为了提交申请同样需要具备API key。

API Key的申请过程很简单,完全免费,没理由不申请API key。如果尚未申请,可以在这里获取API key

2. 未使用最新版API

SafetyNet Attestation API的进化和完善从未停止,并且这个过程中某些接口还产生过变化。最近随着Google Play服务11.0.0版的发布,我们彻底改造了整套SafetyNet API,提供了更易于理解和使用的接口:这套全新API使用SafetyNetClient取代了SafetyNetApi,后者已被停用,因此请务必更新你的实现,使用该API的最新版本。

大部分设备应该已经安装了最新版Google Play服务,但如果设备没有安装Google Play服务,或没有使用最新版本,此时使用SafetyNet Attestation API可能导致应用无法响应或崩溃。为了防止出现这种问题,可以在使用该API之前检查已安装的Google Play服务版本

3. 错误地使用随机数

SafetyNet Attestation API可以让开发者设置一个随机数(Nonce)体现每次API调用时的全局唯一性。通过这个功能可以防止恶意用户重复使用已经成功认证的结果取代未成功认证的结果(这也叫做重播攻击(Replay Attack))。

创建随机数的好办法之一是在服务器上使用密码学上足够安全的随机函数创建一个足够大(16字节甚至更长)的随机数字。SafetyNet的认证响应结果中可以包含你设置的随机数,因此请确保验证返回的随机数与发出的请求中包含的随机数相匹配。

4. 未在你自己的服务器上检查结果

SafetyNet可以针对运行应用的设备状态提供有用的信息,然而如果针对这些信息做出反应的逻辑只在设备本地直接实现,攻击者就可以修改你的应用并绕过你执行的任何检查。

为了防止这种情况,应当在自己能够控制并信任的服务器上运行这些逻辑,借此对认证结果进行验证并根据结果强制执行所需的操作。

5. 在生产环境中使用测试专用的认证验证服务

为了简化SafetyNet Attestation API的开发和测试,Google提供了一个在线验证服务,该服务可以使用简单的HTTPS请求检查SafetyNet验证结果的数字签名。

但是按照设计,这个服务仅是面向测试用途,具备非常严格的用量限额,并且无法通过申请增大。因此你应该在自己服务器上实现一套不依赖Google服务器的数字签名验证逻辑。大部分JWT库提供了签名验证函数,我们也提供了代码示例,向大家展示如何通过Java和C#进行验证。我们还计划在未来提供面向更多语言的示例。

6. 未检查随机数、时间戳、APK名称和哈希

SafetyNet Attestation API以完整性和兼容性检查而著称,该API可通过ctsProfileMatchbasicIntegrity返回检查结果。虽然这两个值确实非常有用,但你还应当检查回应中包含的其他值,其中也包含了很多重要信息。

例如可以按照上文介绍的那样使用nonce将回应与请求相匹配,并可使用timestampMs检查发出请求到收到回应之间经过了多长时间。如果在发出请求后,延误了数小时甚至数天才收到回应,那么这种情况就非常可疑了。

你还可以使用apkPackageName检查发出认证请求的APK名称,并将apkDigestSha256apkCertificateDigestSha256与你的应用在Google Play中的签名APK相匹配,借此判断已安装应用的完整性。

另外要注意回应信息整体的可信与否取决于ctsProfileMatchbasicIntegrity的结果。对于一个basicIntegrity检查失败的被攻陷设备,想伪造回应中的其他值并不是什么难事。

7. 为能理解ctsProfileMatchbasicIntegrity的差异

SafetyNet Attestation API最初只提供了一个名叫basicIntegrity的值,借此帮助开发者判断设备的完整性。随着该API的逐渐完善,我们新增了一种更严格的检查,其结果会包含在名为ctsProfileMatch的值中,这个值可以帮助开发者更细致地评估运行应用的设备。

大体上来说,basicIntegrity可以告诉你设备及其API的常规完整性情况。已Root的设备、模拟器、虚拟设备,以及有篡改迹象(例如使用API钩子)的设备basicIntegrity检查会失败。

另一方面,ctsProfileMatch可以帮你更严谨地判断设备的兼容性。只有被Google认证且未经修改的设备可以成功通过ctsProfileMatch检查。如果设备存在下列情况,将无法成功通过ctsProfileMatch检查:

8. 未实施验证时间检查策略

SafetyNet Attestation API可以针对设备发起验证请求那一刻的状态提供快照。成功的验证结果并不一定意味着设备也曾在过去成功通过了验证,或未来能够继续成功通过验证。

由于这种验证是一种时间点检查,因此你应该规划出适当的策略,决定需要在什么时候发起验证请求。例如可以要求用户进行应用内购买之前必须成功通过验证,在上一次成功验证若干天后重新进行验证,每次启动应用时进行验证,每次重启动之后验证,或按照任何其他针对你的应用来说有必要的时候进行验证。

但是也要注意,验证请求会产生很大的运算量,会耗费设备的电池和带宽,并且会占用你的配额。建议制定合理计划,以最少数量的验证检查满足应用的具体要求。

9. 使用SafetyNet Attestation API结果作为预防滥用的唯一指标

很多人会想当然地认为SafetyNet Attestation API足以帮助自己获得保护设备防范滥用所需的全部机制,并且会只使用这套API来构建自己的反滥用系统。

SafetyNet Attestation API只能帮你了解设备状态,无法帮你了解用户意图,而用户意图需要通过反滥用系统检测才能获知。因此你应该同时考虑其他机制,例如访问日志和行为模式,借此更精确地检测用户滥用情况,绝不应该仅因为该API验证失败就屏蔽用户。此外还有很多其他因素会导致验证失败,例如网络连接问题、配额问题以及传输问题。

换句话说,并非所有未能通过验证的用户都是滥用的用户,也并非所有滥用的用户一定会验证失败。如果仅凭验证结果屏蔽用户,可能会漏掉验证成功的滥用用户,此外也有可能因此而错误地屏蔽了由于非滥用的其他因素导致未能成功通过验证的合法、忠实用户。

10. 未积极监视并管理你的用量配额

正如上文所述,SafetyNet Attestation API的服务速率有一定限制,默认情况下每个API key每天有10,000个请求的配额上限。虽然这个配额对大部分开发、测试和新发布的应用来说已经足够了,但随着用户数的增加,你的应用可能很快就会用到配额上限。

为了防止无意间达到配额限制导致验证出错,应该构建一套监视API用量的系统,并在即将达到配额上限后发出警告,以便随时申请提升配额。此外也应该针对由于达到配额限制而导致的验证失败做好相应准备,避免在这种情况下屏蔽用户。

如果即将达到配额上限,或者可能因为短期峰值导致超出配额上限,你可以提交这个表单申请短期或长期提升API key的配额。提升过程以及提升后的配合同样是免费的。

作者:Oscar Rodriguez,阅读英文原文10 things you might be doing wrong when using the SafetyNet Attestation API

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注