应用开发最佳实践

引言

转自 Application developer best practies。部分内容有编辑。

正文

该文档包含应用程序开发人员的最佳实践,以帮助你为Android用户和设备开发和释放安全的应用程序。最佳实践涵盖四个方面:
1.系统安全:确保核心操作系统的安全性
2.应用安全:确保应用的安全性
3.网络安全:确保网络通信的安全
4.隐私:允许用户控制数据的处理

系统安全

本节包含确保核心Android操作系统安全性的建议。

Biometric authentication

一定要小心谨慎地处理用于用户认证的生物认证数据。从Android 9.0开始,应用程序可以利用新的BiometricPrompt API。支持在Android 8.1和更早的设备上使用support library的方式集成使用。Android 9.0 CDD中包含关于生物认证的更详细和明确的要求。

后门

Android应用程序不应该有任何后门或方法绕过正常安全机制来访问系统或数据。为了防止后门,有以下可以做的:
1.使用行业认可的应用程序漏洞扫描工具来扫描应用程序所使用的所有第三方库和组件。您对应用程序中所有第三方组件的行为负责。
2.上传应用程序到google play扫描,然后使用google play保护。您可以上传应用程序而不发布。

设备驱动程序访问

只有可信代码才有直接访问设备驱动程序的权限。
首选架构是提供一个单用途守护进程,该守护进程代理对驱动程序的调用并限制驱动程序对该守护进程的访问。确保驱动设备节点不是全局可读的或可写的。CTS包括检查暴露的驱动程序实例的测试。

应用安全

本节包含确保应用程序安全性的建议。

源码审查

源代码审查可以检测广泛的安全问题。Android大力鼓励手动和自动源代码审查。
1.在所有使用Android SDK的应用程序代码上运行Android Link,并纠正所有被标识的问题。
2.应该使用能够检测内存管理问题(如buffer overflows和off-by-one errors)的自动化工具分析native code。
3.Android系统支持许多LLVM消毒器,例如AddressSanitizer和UndefinedBehaviorSanitizer,它们可用于内存相关问题的运行时分析。所有消毒器都应该打开,除非有明确的理由。在Android中通过libFuzzer结合fuzzing,可以发现需要进一步调查的不寻常的边缘情况。

应用权限

因为Android应用程序彼此之间隔离。应用程序必须明确地共享资源和数据,需要通过声明基本类型未提供的额外功能所需的权限来实现这一点,包括访问诸如照相机之类的设备特性。

请求权限

您应尽量减少应用程序请求的权限数量。减少对敏感权限的访问降低了无意中滥用这些权限的风险,提高了用户的使用率,并使应用程序不易受到攻击。一般来说,如果一个权限不是必须的,请不要请求它。如果有一个功能必须使用某个权限,否则应用程序不能运行,请使用清单文件中的元素声明它。尝试以不需要任何权限的方式设计应用程序。下面是一些例子:
1.为您的应用程序创建一个GUID,而不是请求访问设备信息来创建唯一的标识符。有关的详细信息,请参阅Handling user data
2.使用getExternalFilesDir将数据存储在内部存储器或应用程序的专用外部存储器中,而不是使用需要权限的外部存储器
3.使用标准Intent来避免请求权限。例如,使用ACTION_IMAGE_CAPTURE而不是持有camera的权限,使用ACTION_CALL而不是持有phone的权限。
除了请求权限之外,您的应用程序还可以使用清单中的element来保护暴露给其他应用程序并对安全性敏感的IPC,例如ContentProvider。一般来说,我们建议尽可能使用访问控制而不是让用户确认权限,因为权限可能让用户感到困惑。例如,考虑使用Android提供的特定选择器对话框进行单个元素访问,或者,如果需要更广泛的访问,单个开发人员提供的多个应用程序之间的IPC通信权限上,可以考虑使用签名保护级别。
不要泄漏受权限保护的数据。当应用程序通过IPC暴露数据时,这就会发生。因为您的应用程序具有访问IPC的权限。应用程序的IPC接口的客户端可能没有相同的数据访问权限。关于这个问题的频率和潜在影响的更多细节出现在USENIX发表的研究论文《Permission Re-Delegation: Attacks and Defenses》中。

创建权限

尽量在满足安全要求的同时定义尽可能少的权限。对于大多数应用程序来说,创建新权限相对来说并不常见,因为系统定义的权限覆盖了许多情况。在合适的情况下,使用现有权限执行访问检查。如果必须创建新的权限,请考虑是否可以用签名保护级别来完善签名权限对用户是透明的,并且只允许由与执行权限检查的应用程序相同签名的应用程序访问。如果仍然需要新的权限,则使用标签在应用程序清单中声明。希望使用新权限的应用程序可以通过在各自的清单文件中添加一个标签来引用它
如果你创建的是危险权限,则需要考虑的复杂性有很多:1.权限必须有一个字符串,该字符串简洁地向用户表达他们做出的安全决策。
2.权限字符串必须本地化到许多不同的语言。
3.应用程序可能在未安装权限的创建者时请求权限。
所有这些都对作为开发人员的您提出了重大的非技术挑战,同时这也使您的用户感到困惑,这就是为什么我们不鼓励使用危险权限。

数据存储

Android上应用程序最常见的安全问题是,您保存在设备上的数据是否可被其他应用程序访问。在设备上保存数据有三种基本方法:
1.Internal storage
2.External storage
3.Content providers

Internal storage

默认情况下,在内部存储中创建的文件只能应用程序自身访问。Android实现了这种保护,这对大多数应用程序来说都是足够的。
一般来说,避免IPC文件的MODE_WORLD_WRITEABLE或MODE_WORLD_READABLE模式,因为它们不提供限制对特定应用程序的数据访问的能力,也不提供数据格式的任何控制。如果希望与其他应用程序进程共享数据,可以考虑使用content provider,它为其他应用程序提供读写权限,并且可以根据具体情况动态授予权限。
为了对敏感数据提供额外的保护,可以使用应用程序不能直接访问的密钥对本地文件进行加密。例如,可以将密钥放在密钥存储库中,并用未存储在设备上的用户密码来保护密钥。虽然这不能保护数据免遭可能监视用户输入密码的根本危害,但是它可以在没有文件系统加密的情况下为丢失的设备提供保护。还可以使用StorageManager.isEncrypted()来确定文件路径是否已经被系统加密,以避免双重加密的性能开销。

External storage

在外部存储(例如SD卡)上创建的文件是全局可读和可写的。因为外部存储可以由用户移除,也可以由任何应用程序修改,所以不要使用外部存储来存储敏感信息。

在处理来自外部存储的数据时,您应该执行输入验证,就像从任何不受信任的源中获取数据一样。在动态加载之前,不应将可执行文件或类文件存储在外部存储中。如果您的应用程序确实从外部存储中检索可执行文件,那么在动态加载之前,应该对文件进行签名和加密验证。

Content providers

Content providers提供了一个结构化的存储机制,可以只限于您自己的应用程序,也可以暴露出来以允许其他应用程序访问。如果不打算为其他应用程序提供对ContentProvider的访问,请在应用程序清单中将它们标记为android:export=false。否则,将Android导出属性设置为true,以允许其他应用程序访问存储的数据。
创建供其他应用程序使用的ContentProvider时,可以指定单个读写权限,也可以指定不同的读写权限。您应该将权限限制在完成手头任务所需的权限上。请记住,稍后添加权限以公开新功能通常比取消权限并影响现有用户更容易。
如果使用Content providers仅在自己的应用程序之间共享数据,则最好使用android:protectionLevel属性设置签名保护。签名权限不需要用户确认,因此当访问数据的应用程序使用相同的密钥签名时,它们能提供更好的用户体验和更加受控的对内容提供商数据的访问。
Content providers还可以通过声明android:grantUriPermissions属性并在激活组件的Intent对象中使用FLAG_GRANT_READ_URI_PERMIS.和FLAG_GRANT_WRITE_URI_PERMIS标志来提供更细粒度的访问。这些权限的范围可以进一步受标签限制。
访问Content providers时,选择参数始终过滤不可信输入,以避免可能的SQL注入攻击。在实现内容提供程序时,始终使用启用了setStrict()的SQLITQueryBuilder构造查询,以防止SQL注入攻击。
不要对写权限有错误的安全感。写权限允许SQL语句,这些语句允许使用创造性WHERE子句和解析结果来确认某些数据。例如,攻击者可以通过仅在电话号码已经存在的情况下修改一行来探测呼叫日志中特定电话号码的存在。如果Content provider数据具有可预测的结构,则写入权限可以等效于同时提供读取和写入。

输入验证

输入验证不足是影响应用程序的最常见安全问题之一,无论它们运行在什么平台上。Android有平台级别的对策,可以减少应用程序对输入验证问题的暴露,您应该尽可能使用这些特性。还要注意,类型安全语言的选择往往会降低输入验证问题的可能性。
如果使用native code,则从文件读取、通过网络接收或从IPC接收的任何数据都有可能引入安全问题。最常见的问题是缓冲区溢出、释放后使用和off-by-one错误。Android提供了许多技术,如ASLR和DEP,它们降低了这些错误的可利用性,但是它们并不能解决根本问题。通过仔细处理指针和管理缓冲区,可以防止这些漏洞。
基于字符串的动态语言,如JavaScript和SQL,由于转义字符和脚本注入,也会遇到输入验证问题。
如果您正在使用的数据包含提交给SQL数据库或内容提供者的查询,SQL注入可能是一个问题。最好的防御是使用参数化查询,正如上面关于Content providers的讨论中所讨论的。将权限限制为只读或只写也可以减少与SQL注入有关的危害。
如果不能使用上述安全特性,则应确保使用结构良好的数据格式,并验证数据是否符合预期格式。虽然黑名单字符或字符替换可以是一个有效的策略,但这些技术在实践中容易出错,应该尽可能避免。

动态代码加载

我们强烈反对从应用程序APK外部加载代码。这样做显著地增加了由于代码注入或代码篡改导致的APP妥协的可能性。它还增加了版本管理和应用程序测试的复杂性。会使得无法验证应用程序的行为,因此在某些环境中它可能被禁止。
如果您的应用程序确实动态加载代码,那么关于动态加载的代码,要记住的最重要的事情是它以与应用程序APK相同的安全权限运行。用户根据您的身份决定安装应用程序,并且用户希望您提供的任何代码,包括动态加载的代码,在该应用程序中运行。
与动态加载代码相关的主要安全风险是代码需要来自可验证的源。如果模块直接包含在您的APK中,则它们不能被其他应用程序修改。无论代码是本地库还是使用DexClassLoader加载的类,都是如此。许多应用程序试图从不安全的位置加载代码,例如通过未加密协议从网络下载,或者从外部存储等可写位置下载代码。这些位置可以允许网络上的人修改传输中的内容,或者允许用户设备上的其他应用程序修改设备上的内容。

Native code

一般来说,您应该使用Android SDK进行应用程序开发,而不是使用Android NDK使用native code。使用本机代码构建的应用程序更复杂、可移植性更差,并且更可能包含常见的内存损坏错误,例如缓冲区溢出。
Android是使用Linux内核构建的,如果您使用native code,那么熟悉Linux开发安全最佳实践尤其有用。Linux的安全实践超出了本文的范围,但是最受欢迎的资源之一是Secure Programming HOWTO - Creating Secure Software
Android和大多数Linux环境之间的一个重要区别是应用沙盒。在Android上,所有应用程序都运行在应用程序沙箱中,包括那些用native code编写的应用程序。从最基本的层面来看,对于熟悉Linux的开发人员来说,考虑它的一个好方法就是知道每个应用程序都被赋予了具有非常有限的权限的惟一UID。Android Security Overview对此进行了更详细的讨论,您应该熟悉应用程序权限,即使您正在使用native code。

虚拟机

Dalvik是Android的运行时虚拟机(VM)。Dalvik是专门为Android构建的,但是关于其他虚拟机中安全代码的许多关系也适用于Android。一般来说,您不应该担心与虚拟机有关的安全问题。您的应用程序运行在安全沙箱环境中,因此系统上的其他进程无法访问您的代码或私有数据。
如果您对学习更多有关虚拟机安全性的知识感兴趣,请熟悉一些关于这个主题的现有文献。两个比较受欢迎的资源是:
Securing Java
Related third-party projects
本文档着聚焦于Android的特性或不同于其他VM环境的部分。对于在其他环境中具有VM编程经验的开发人员来说,在为Android编写应用程序时,存在两个大问题:
一些虚拟机,例如JVM或.NET运行时,充当安全边界,将代码与底层操作系统功能隔离。在Android上,Dalvik VM不是一个安全边界——Application Sandbox是在OS级别实现的,因此Dalvik可以在没有任何安全约束的情况下与相同应用程序中的native code进行互操作。
由于移动设备上的存储空间有限,开发人员通常希望构建模块化应用程序并使用动态类加载。这样做时,要考虑在哪里检索应用程序逻辑以及在本地存储它。不要使用来自未验证的源(例如不安全的网络源或外部存储)的动态类加载,因为该代码可能被加入恶意的行为。

应用发布

Google play提供了在不执行完整系统更新的情况下更新应用程序的能力。这可以加快对安全问题的响应和新特性的交付,同时也确保应用程序具有唯一包名的方法。
1.上传你的应用程序到Google play,以允许自动更新,而不需要一个完整的空中(OTA)更新。上载但未发布的应用程序不能直接由用户下载,但Google play上的应用程序仍然被更新。先前安装应用程序的用户可以重新安装或安装在其他设备上。
2.创建一个与你的公司有关联的应用程序包名称,例如使用公司商标。

应用签名

App签名在设备安全中起着重要的作用,也用于权限检查以及软件更新。在选择用于签署应用程序的密钥时,考虑应用程序是否只在单个设备上使用还是在多个设备上通用是很重要的。
1.应用程序不能用公开的密钥签署。
2.用于签署应用程序的密钥应当以与处理敏感密钥的行业标准实践相一致的方式进行管理,包括提供有限、可审计访问的HSM。
3.应用程序不应用平台密钥进行签名。否则会让应用程序拥有访问平台的签名权限,这些权限非常强大,并且仅供操作系统的组件使用。如果你有比普通应用程序更需要特权的应用程序,你可以把它们变成一个特权应用程序。请确保使用白名单锁定特权应用程序权限。
4.如果您用Google托管您的APK签名密钥,并且您的上传密钥丢失或受损,那么您可以与Google联系以撤销旧的上传密钥并生成新的密钥。这只适用于Google play上的应用程序。
5.同一个包名的应用程序不应该用不同的密钥签名。这经常发生在为不同设备创建应用程序时,尤其是在使用平台密钥时。如果应用程序是独立于设备的,则在设备上使用相同的密钥。如果应用程序是特定于设备的,则在每个设备和密钥上创建唯一的包名。

网络安全

本节包含确保网络通信安全的建议。

网络

网络事务本质上存在安全风险,因为它们涉及向用户传输可能私有的数据。所有到目的地的网络连接都应该被正确地加密,以防止在途中窃听和修改,无论连接的内容如何,这都是真理。详情请参阅我们的开发者峰会。

IP网络

Android上的网络与其他Linux环境没有明显不同。关键的考虑是确保使用适当的协议,例如用于安全通信的HttpsURLConnection 。考虑到Android设备与潜在的恶意无线网络(例如不安全的Wi-Fi网络)连接的频率,强烈鼓励所有通过网络进行通信的应用程序使用安全网络。至于Android P,默认情况下,尝试使用未加密的连接将导致IOException。
可以使用SSLSocket类实现经过身份验证的、加密的套接字级通信,但是正确验证服务器证书的主机名与目的地匹配是至关重要的,因为SSLSocket在默认情况下不这样做,这可以使用HttpsUrlConnection.getDefaultHostnameVerifier的标准HostnameVerifier来完成。
有些应用程序使用本地主机网络端口来处理敏感的IPC,这是不安全的,不能使用。这是因为这些接口可以由设备上的其他应用程序访问。相反,使用Android IPC机制,在那里可以进行身份验证,例如使用服务。绑定到INADDR_ANY比使用回环更糟糕,因为您的应用程序可以从任何地方接收请求。
不要盲目信任来自远程源的数据,特别是如果数据是通过HTTP或其他不安全协议传递的。这还包括在WebView中验证输入。

电话网络

SMS协议主要是为用户通信设计的,并不适合希望传输数据的应用程序。由于SMS的限制,您应该使用Firebase Cloud Messaging (FCM)和IP网络将数据消息从Web服务器发送到用户设备上的应用程序。
当心SMS既不加密也不在网络或设备上进行强认证。特别是,任何SMS接收器都应该预期恶意用户可能已经将SMS发送到您的应用程序。不要依赖未经认证的SMS数据来执行敏感命令或向设备传送敏感数据。此外,您应该知道,SMS可能会受到网络上的欺骗和/或拦截。在Android驱动的设备本身上,SMS消息作为广播意图传输,因此它们可以被具有READ_SMS权限的其他应用程序读取或捕获。

进程间通信

一些应用程序试图使用传统的Linux技术(如网络套接字和共享文件)来实现IPC。但是,您应该使用Android系统功能来IPC,比如Intent、Binder或Messenger with Service,以及BroadcastReceiver。Android IPC机制允许您验证连接到IPC的应用程序的身份,并为每个IPC机制设置安全策略。
许多安全元素在IPC机制之间共享。如果IPC机制不打算供其他应用程序使用,则在组件的manifest元素中将android:export属性设置为false。这对于在同一UID中由多个进程组成的应用程序非常有用,或者如果您在开发后期决定不将功能公开为IPC,但是您不想重写代码。
如果您的IPC对于其他应用程序是可访问的,您可以通过使用该元素来应用安全策略。如果IPC是在您自己的使用相同密钥签名的独立应用程序之间,那么最好在android:protectionLevel中使用签名级别权限。

使用intents

对于activities和broadcast receivers,intents是Android中异步IPC的首选机制。根据您的应用程序需求,您可以使用sendBroadcast()、sendOrderedBroadcast()或明确intents发送给特定应用程序组件。出于安全目的,首选的是明确的intent。
注意:如果使用intent绑定到服务,请确保使用明确的intent的应用程序是安全的。使用隐式intents启动服务是一种安全隐患,因为您不能确定什么服务将响应该意图,并且用户无法看到哪个服务启动。从Android 5.0开始(API级别21),如果你用一个隐式的intent调用bdIdService(),系统会抛出一个异常。
请注意,有序广播可以由接收者使用,因此它们可能不会被传递到所有应用程序。如果发送的intent必须传递给特定的接收方,则必须使用通过名称声明接收方的显式intent。
intent的发送者可以通过使用方法调用指定非空权限来验证收件人是否具有权限。只有具有该权限的应用程序才接收到该intent。如果广播意图内的数据可能是敏感的,则应考虑应用权限以确保恶意应用程序在没有适当权限的情况下不能注册以接收这些消息。在这种情况下,您也可以考虑直接调用接收方,而不是发送广播。
intent过滤器不应被认为是安全特性。组件可以用显式intent调用,并且可能没有符合intent过滤器的数据。为了确认它为被调用的接收机、服务或活动进行了适当的格式化,请在intent接收机内执行输入验证。

使用services

服务通常用于提供其他应用程序使用的功能。每个服务类必须在其清单文件中有一个相应的声明。
默认情况下,服务不会暴露,不能被任何其他应用程序调用。但是,如果向服务声明添加任何intent筛选器,则默认情况下暴露。最好是显式声明android:exported属性,以确保它的行为符合你的意愿。服务也可以使用android:permission属性来保护。通过这样做,其他应用程序需要在自己的清单中声明相应的元素,以便能够启动、停止或绑定到服务。
提示:如果应用程序针对Android 5.0(API级别21)或更高版本,则应该使用JobScheduler来执行后台服务。有关JobScheduler的更多信息,请参见其API参考文档。
服务可以通过在执行调用实现之前调用checkCallingPermission()来保护具有权限的单个IPC调用。您应该使用清单中声明的权限,因为那些不太容易被疏忽。
注意:不要混淆客户端和服务器权限;确保被调用的应用程序具有适当的权限,并验证是否向调用的应用程序授予了相同的权限。

使用binder和messenger接口

使用binder或Messenger是Android中 RPC-style IPC的首选机制。它们提供了一个定义良好的接口,如果需要的话,可以实现端点的相互认证。
您应该以不需要特定于接口的权限检查的方式设计应用程序接口。 Binder and Messenger没有在应用程序清单中声明,因此您不能直接向它们应用声明性权限。它们通常继承实现它们的Service或Activity的应用程序清单中声明的权限。如果正在创建需要身份验证或访问控制的接口,则必须显式地将这些控件作为代码添加到Binder或Messenger接口中。
如果提供的接口确实需要访问控制,则使用checkCallingPermission()来验证调用方是否具有所需的权限。在代表调用者访问服务之前,这一点特别重要,因为应用程序的标识被传递到其他接口。如果正在调用服务提供的接口,当没有权限访问给定服务时,则bindService()调用可能会失败。如果调用您自己的应用程序在本地提供的接口,那么使用clearCallingIdentity()方法满足内部安全检查可能是有用的,该方法将调用者权限屏蔽为应用程序的权限。您可以通过使用RealCeCalpIdItId()方法来恢复调用方权限。
有关使用服务执行IPC的更多信息,请参见绑定服务。

使用广播接收器

广播接收器处理intent发起的异步请求。
默认情况下,接收器被暴露并可以被任何其他应用程序调用。如果BroadcastReceiver打算供其他应用程序使用,你需要在应用清单中声明安全权限。这阻止了没有适当权限的应用程序向广播接收器发送意图。

安全监听套接字

监听套接字应该谨慎使用,并且通常不应该有任何开放式监听套接字被Android应用程序暴露。
在没有空中(OTA)更新的情况下,监听套接字必须能够被禁用。这可以使用服务器或用户设备配置更改来执行。
对于使用套接字的本地IPC,应用程序必须使用UNIX域套接字,其访问权限仅限于组。为IPC创建文件描述符,并为特定UNIX组生成+RW。任何客户端应用程序必须在UNIX组内。
具有多个处理器(例如,与应用程序处理器分离的无线电/调制解调器)的一些设备使用网络套接字在处理器之间进行通信。在这种情况下,用于处理器间通信的网络套接字必须使用隔离的网络接口来防止设备上的未经授权的应用程序访问(即,使用iptables来防止设备上的其他应用程序访问)。
处理侦听端口的守护进程必须对错误的数据保持健壮性。谷歌可以使用未经授权的客户端对端口进行模糊测试,并且在可能的情况下,授权客户端。任何崩溃都将被归类为错误的严重程度。
CTS包括检查是否存在打开监听端口的测试。

WebView

因为WebView使用包括HTML和JavaScript的web内容,所以不恰当的使用可能会引入常见的web安全问题,比如跨站点脚本(JavaScript注入)。Android包括许多机制,通过将WebView的能力限制到应用程序所需的最小功能来减少这些潜在问题的范围。
如果您的应用程序在WebVIEW中不直接使用JavaScript,请不要调用StjJavaSpRIPabDebug()。一些示例代码使用此方法,您可能会在生产应用程序中重新使用它,因此如果不需要,请删除该方法调用。默认情况下,WebView不执行JavaScript,因此跨站点脚本是不可能的。
特别小心使用addJavaScriptInterface(),因为它允许JavaScript调用通常为Android应用程序保留的操作。如果使用它,只将AdjJavaScript接口()公开到所有输入都值得信任的网页。如果允许不受信任的输入,不可信的JavaScript可以在应用程序中调用Android方法。一般来说,我们建议将AdjJavaScript接口()仅暴露在应用程序APK内的JavaScript中。
如果应用程序使用WebView访问敏感数据,则可能希望使用clearCache()方法删除本地存储的任何文件。还可以使用服务器端头(如无缓存)来指示应用程序不应该缓存特定的内容。
为了确保您的应用程序没有暴露SSL中的潜在漏洞,请使用可更新的安全提供程序对象,如更新您的安全提供程序以防止SSL漏洞。

凭证处理

为了使钓鱼攻击更加明显,并且不太可能成功,请最小化请求用户凭证的频率相反,使用授权令牌并刷新它
在可能的情况下,不要在设备上存储用户名和密码。相反,使用用户提供的用户名和密码执行初始身份验证,然后使用短期的、特定于服务的授权令牌。
可以使用Access管理器访问多个应用程序可访问的服务。如果可能的话,使用ActualMe管管理类调用基于云的服务,不要在设备上存储密码。
在使用AccountManager检索帐户之后,在传递任何凭据之前使用CREATOR,这样就不会无意中将凭据传递给错误的应用程序。
如果凭证仅由您创建的应用程序使用,则可以使用checkSignature()验证访问AccountManager的应用程序。或者,如果只有一个应用程序使用凭据,则可以使用密钥库进行存储。

隐私

本节包含确保Android用户对数据的处理有控制权的建议

处理用户数据

通常,用户数据安全的最佳方法是最小化日志记录和访问敏感或个人用户数据的API的使用。如果您可以访问用户数据,并且可以避免存储或传输,则不要存储或传输数据。考虑使用散列或其他不可逆形式的数据来实现逻辑。例如,您的应用程序可能使用电子邮件地址的不可逆散列作为主键,以避免发送或存储电子邮件地址。这减少了无意中暴露数据的机会,也减少了攻击者试图利用您的应用程序的机会。

如果您的应用程序访问个人信息,如密码或用户名,请记住,一些司法管辖区可能要求您提供隐私政策,解释您使用和存储这些数据。遵循安全性的最佳做法,最大限度地减少对用户数据的访问也可以简化依从性。

您还应该考虑您的应用程序是否可能无意中将个人信息暴露给其他方,例如用于广告的第三方组件或应用程序使用的第三方服务。如果你不知道为什么一个组件或服务需要个人信息,不要提供它。一般来说,减少应用程序对个人信息的访问减少了该领域的潜在问题。

如果应用程序需要访问敏感数据,请评估是否需要将其发送到服务器或是否可以在客户端上运行该操作。只要可能,使用客户端上的敏感数据运行任何代码,以避免发送用户数据。此外,请确保您不会无意中通过过度许可的IPC、可写文件或网络套接字将用户数据暴露到设备上的其他应用程序。过度许可的IPC是泄漏许可保护数据的特殊情况,在请求权限部分中讨论。

如果需要一个GUID,则创建一个大的、唯一的数字并存储它。不要使用电话标识符,如电话号码或IMEI,这是个人可识别的。本主题将在Android开发者博客中详细讨论。

在写入设备日志时要小心。在Android中,日志是一个共享资源,拥有READ_LOGS权限的应用程序可以访问它。尽管电话日志数据是临时的,并且在重新启动时擦除,但是用户信息的不当日志记录可能无意中将用户数据泄露给其他应用程序。除了不记录PII,生产应用程序应该限制日志使用。为了方便地实现这一点,使用调试标志和自定义日志类具有易于配置的日志记录级别。

Logging数据

Logging数据增加了暴露该数据的风险,并降低了系统性能。由于敏感用户数据的记录,发生了多起公共安全事件。
应用程序不应记录可能包含敏感信息的第三方应用程序提供的数据。
除非绝对需要提供应用程序的核心功能,否则应用程序不能将任何个人可识别信息(PII)作为正常操作的一部分进行日志记录。
CTS包括检查日志中是否存在潜在敏感信息的测试

Metrics收集

确保Android应用程序中任何度量集合的最佳实践是很重要的,包括:
确保未经明确、知情和有意义的用户同意,不收集和报告Metrics标准。
除了少数例外,仅收集支持服务可靠性所必需的Metrics。
避免尽可能收集可识别或潜在敏感的数据,如硬件标识符。
尽可能确保数据足够的聚集和匿名。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,391评论 25 707
  • 用两张图告诉你,为什么你的 App 会卡顿? - Android - 掘金 Cover 有什么料? 从这篇文章中你...
    hw1212阅读 12,680评论 2 59
  • (李克富老师点评训练营25/90) 李克富||学生是心理老师的掘墓人而非跪拜者 - 简书 李克富||吾爱吾师,吾更...
    人生心经阅读 559评论 0 1
  • 为何选择 Flux 设计上遇到的问题 最初在接触 Flux 时就有一种惊艳的感觉,长久以来在设计上所出现的困扰似乎...
    _WZ_阅读 7,922评论 2 9
  • 感恩妈妈一早就过来带光宝并辛苦的做家务,感恩,感恩老婆光宝的快乐成长,感恩早起运用种子法则,感恩觉察内心的感受使我...
    2月31日阅读 187评论 0 4