Android 安全小贴士

来源:互联网 发布:linux ftp 权限控制 编辑:程序博客网 时间:2024/06/05 22:52

Android已经把减少安全方面问题的特色功能内置到了操作系统中。系统关于安全方面的设计可以使我们的app用默认的文件权限,且避免了我们困难的选择决定怎么用她。

安全功能的一些核心部分可以帮助构建安全的apps,包括:

1、独立与其他app和代码执行的Android app 沙盒。

2、强健的通用安全函数app框架,比如加密、权限、安全的进程间通讯(Interprocess communication)。

3、减少常见的内存管理错误风险的技术,比如:随机地址空间分配 (ASLR)、(NX)、(ProPolice)、(safe_iop)、(OpenBSD dlmalloc)、(OpenBSD calloc) 、和 (Linux mmap_min_addr)

4、可保护设备数据丢失或被盗的加密文件系统。

5、限制对系统功能和用户数据访问的User-granted权限

6、独立的App基础上定义权限来控制每个App数据。


数据存储

在Android的应用程序保存在设备上的数据,其他应用程序是否可以访问这是最常见的安全问题。有三种保存数据的方式:

A、使用内部存储

内部存储的文件默认的只用自己的app能够访问。这种保护数据机制由Android系统来实现,对于大多数的app已经足矣。

通常情况下,避免将MODE_WOELD_WRITEABLE或MODE_WORLD_READABLE模式,使用在进程间通讯的文件上。因为他们对于特殊的apps不能限制访问任何数据,也不提供任何控制数据格式。如果你想给其他app进程共享数据,可能需要考虑用content provider,她可以给其他app提供读和写的权限,并且可以给针对特定事件进行动态授权。

对于敏感数据提供额外的保护机制,可能需要选择用一个key加密本地文件,这样可以使app不直接的访问到数据文件。例如,这个可以key需要用户密码的情况下存储到密码存储库中并保护起来,而不存储在设备上。监测用户输入的密码可以保护未加密保护的数据,当然这种情况发生在设备丢失时。

B、使用扩展存储

在扩展存储下创建的文件是全局可以读和写的,比如在SD Cards 上。因为扩展存储可以被用户移除,也可以被其他的任何app所修改,所以在扩展存储上一般不存储敏感的信息。

对于不信任的资源的数据,当在处理来自扩展存储设备的数据时应该执行输入验证操作。我们强烈的不建议将可执行的类文件放到扩展存储设备上,用来动态的加载他们。如果你的应用程序从外部存储检索可执行的文件,这些文件应该在动态加载之前进行签署和加密验证。

C、使用Content Providers

content provider 提供一个结构性的存储机制,她能够限制在自身app使用或运行其他app访问的出口。如果不打算让其他的app访问那就需要在app的manifest文件中标明 android:exported=false属性。相反,如果允许其他的app访问的话,需要在文件中标明android:exported=true; 

当构建时ContentProvider就会作为其他app来用的出口,对于读写能够指定单独的权限,或在manifest文件中对于读写指定明显的权限。我们要求能够完成处理任务来限制你的请求权限。记住,添加权限后在暴露出新功能是很容易的事情。

用content provider在自家的app之间共享数据,把android:protectionLevel="signature"来保护数据发方式更可取。签名的权限不需要用户来确认,因此就会提供一个更好的用户体验并且更好的控制content provider数据,这些都是发生在用同样的key来签名的app间访问数据时。

Content provider 能够提供更加颗粒细化的访问数据权限,但是这要声明android:grantUriPermissions并且在Intent中用FLAG_GRANT_READ_URI_PERMISSION和FLAG_GRANT_WRITE_URI_PERMISSION 标签。这些权限的范围能够用用<grant-uri-permission element> 来更进一步的限制。

当访问content provider时,用query(),update(),和delete()等参数化的方法,可以避免来自不可靠程序资源的SQL注入。注意,如果是由连接用户数据前提交方法selection参数,只是使用参数化方法是不够的。

没有写权限的安全感是虚假的。考虑允许SQL语句写权限,使数据证实使用创造性的WHERE子句和解析结果。例如,例如,攻击者可能会探测在电话日志中存在的一个特定存在的电话号码,只通过修改一行,电话号码就存在了。如果content provider的数据结构可以预测,写权限可能就相当于提供了读和写。

D、使用权限

因为android互相之间都是独立沙盒app,所以app必须明确共享资源和数据。为此,他们声明不需要额外功能的权限提供的基本沙箱,就像访问相机设备

E、请求权限

我们要求你的app请求最少的权限。没有访问敏感权限减少无意中滥用这些权限的风险,能够提高用户的接收程度,并且能够使app尽可能少的遭收到攻击。一般而言,如果一个权限对于app的功能不被请求,那她就不会被要求。

如果用这种方式设计的app不需要任何权限就更好啦。比如,为App创建一个GUID(是一个不变的一个128位的全局惟一标识符),而不是为了请求访问设备信息而创建一个唯一惟一的标识符uuid。

除去请求权限外,app能用<permissions>保护IPC,就像ContentProvider一样安全。一般情况下,我们要求的权限必须通过用户确认,因为某些权限是可以为用户拒绝掉的。

F:创建权限

通常情况下,在满足安全需求同时,应该尽量少的定义权限。创建新的权限在很多app中是很少见的,因为系统定义的权限,已经涵盖了很多的情况。特定的地方,用存在的权限确认访问检查。

G:使用网络

网络传输是有安全风险的,传输的信息可能包含用户隐私。越来越多的人意识到移动设备上的隐私问题,特别是在执行网络传输操作的时候,因此让自己的app用最好的方式保持用户信息安全是非常重要的。

使用IP网络

Android上的网络和Linux的网络没什么不同。关键考虑确定敏感数据的传输用那种适当的协议,例如HttpsURLConnection 网络安全传输。我们宁愿在用HTTP的服务器上使用HTTPS,因为移动设备连接网络经常是不安全的,比如公共wi - fi热点。

用SSLSocket类实现授权、加密通讯交流的级别是很容以实现的。鉴于Android设备使用wi - fi连接到未加密的无线网络的频率,app通过网络传输信息时,强烈建议用安全的网络。

我们可以看到很多app用localhost网络接口处理敏感的IPC。我们不鼓励使用这样的方法,因为这些可能要访问设备上其他的app。您应该使用一个Android IPC机制,就像可行的身份验证服务授权。

使用电话网络

SMS协议主要是为用户沟通而设计的,并不适合于应用程序之间传输数据。由于SMS协议局限性,我们强烈建议使用谷歌云消息传递(GCM)和IP网络从web服务器发送数据信息用户设备的应用程序

注意短信既不加密也不强烈网络或设备上验证。特别是,短信接收者应该期待恶意用户可能已经发送短信到您的应用程序上-为了执行敏感的命令而不依赖未经身份验证的短信数据。同时,你应该意识到短信可能在网络上被欺骗和/或截取。安卓设备本身而言,短信通过广播意图传输,因此他们就可能会被READ_SMS许可权限的其他应用程序读或捕捉。

K:执行输入验证

输入验证不足是一种最常见的影响应用程序的安全问题,不管在哪个平台上。Android有平台级对策,减少应用程序输入验证的问题,应该在可能的情况下来使用这些功能。还要注意,选择类型安全的语言倾向于减少输入验证问题的可能性。如果您使用Native代码,那么读取文件的任何数据,通过网络获得或收到一个IPC有可能引入一个安全问题。最常见的问题是缓冲区溢出(buffer overflows),use after free,和 off-by-one错误。Android提供了减少这些错误的技术,例如ASLR 和 DEP,但他们解决了根本问题。小心操作指针和管理缓冲可以减少这些。

L:处理用户数据

一般情况下,保护用户数据安全的最好的办法是最少的调用APIs来访问敏感的个人用户信息。如果你已经访问了用户的信息并且能避免或不存储或传送这些信息。最后,考虑是否有一种您的App逻辑可以使用一个散列实现或不可逆的数据形式的方法。例如,app可能用一个email地址的hash值作为一个私钥,来避免传输或存储email的地址。这将会减少暴露数据的几率,并且也会减少攻击者试图利用你的app的机会。

如果GUID是必须的,创建一个大的,独一无二的数并且存储它。不要用phone标示符例如电话号码或IMEI,这些可能跟个人信息有关系。

小心正在写在设备上的日志。在Android上日志资源是共享资源,有READ_LOGS权限的app都能够访问到。这些日志可能会泄露用户数据信息给其他的app。

M:使用WebVIew

因为Webview通过用HTML和JavaScript来渲染web内容,使用不当就会导致像javascript注入这样跨站注入的网络安全问题。Android包含了大量减少潜在问题发生的机制,它要求webview为app兼容最少的功能要求。

如果在app的webview中不直接用JavaScript,不调用setJavaScriptEnabled()方法。一些示例代码使用这个方法,你可能减少在产品中的使用,因此删除那些不必要的方法。默认情况下,webview不可能不执行跨站的脚步Javascript。

使用addJavaScriptInterface()方法要小心,因为他会允许JavaScript调用操作Android程序功能的代码。如果要用他的话,只能在输入被信任的web页面下暴露addJavaScriptInterface()方法。如果不,JavaScript可能就会调用app中的方法。一般来讲,我们建议暴露addJavaScriptInterface仅仅包含在自己的apk中的JavaScript。

如果app用webview访问敏感信息,可能想用clearCache()方法删除一些本地存储的信息。服务器端头文件中no-cache也能用来指示不缓存的内容。

处理凭证

通常情况下,我们要求最少的频率要求用户认证--这样更会引起网络钓鱼攻击的注意,但很少可能会成功。用一个授权token来授权并且刷新他。

可能的话,用户名和密码不要存储到设备上。应该用用户名和密码来初始化权限,并且用一个短暂的声明周期的服务指定授权token。

访问多个apps的Service应该用AccountManager。如果可能的话,就用AccountManager类来操作基于一个云端的服务,而不是在设备上存储密码。

用AccountManager传递Account,CREATOR后,再传入任何的认证,因此以至于不在错误的app中通过认证。

如果凭证只用在自己创建的应用程序中,然后可以用checkSignature()验证的应用程序访问AccountManager。另外,如果只有一个应用程序将使用凭证,可以使用存储库来存储密钥。

O:使用加密

Android提供了一系列广泛的算法加密保护数据。

如果你需要一个安全的隧道,考虑使用HttpsURLConnection或SSLSocket,而不是编写自己的协议。

如果你发现自己需要实现自己的协议,那就使用现有的加密算法AES和RSA的实现之类的密码提供的类。

如果你需要重复使用存储的KeyStore,使用密钥存储库提供的长期密钥的存储和检索的机制。

P:使用内部进程通讯(ipc)

如果不打算让其他app的使用,需要在manifest文件中的元素设置android:exported = "false"。

如果自己的ipc打算访问其他的app,需要通过用<permission>元素应用一个安全的策略。

如果自己的用同一个key签名的app,需要在android:protectionLevel中用signature定义权限级别。

使用intents

使用services

android:exported

android:permission 

 <uses-permission>

 checkCallingPermission()

使用binder和messenger接口

Binder和Messenger通常继承Service和Activity实现声明的权限。

使用broadcast receivers

<receiver> 

R:动态地加载代码

DexClassLoader动态加载apk中dex文件的代码。

S:虚拟机的安全

虚拟机允许在沙盒环境中,其他app不能访问自己的代码或隐私数据。

T:Native代码的安全

通常情况下我们鼓励用android sdk开发,而不是用android ndk。app构建native代码是相当复杂的,更轻便,包括缓冲区溢出等常见的内存泄露错误。如果你要使用native code 对Android使用Linux内核和熟悉Linux开发的安全的实践特别有用。Android和大多数Linux环境中一个重要的区别是应用程序沙箱概念。在Android上,所有应用程序在沙箱中运行,包括那些与native code写的。在最基本的层面上,对于开发人员熟悉Linux每个应用程序分配一个惟一的UID和非常有限的权限,思考一个很好的方式。

0 0
原创粉丝点击