如何构建安全的Android应用

来源:互联网 发布:数据加密标准des 编辑:程序博客网 时间:2024/05/17 02:30

App的安全问题

随着移动操作系统的日趋完善及App开发流程的逐渐成熟,App的安全问题得到越来越多的重视,同时很多App的安全问题被暴露出来,其中又以Android为甚,如App被反编译植入广告、App轻易被抓包、模拟App爬取服务器的数据等等。现在的Android开发者在开发一个App的时候,所想的就不仅仅是实现功能,而是要思考如何才能开发一个安全的应用。

花了两天时间看了《构建安全的Android App》一书,书中概括性地提到了关于Android安全的方方面面,大部分都是我们日常开发中遇到的情况,也许有的方面你注意到了,也许有的方面你还没有注意。根据此书提到的部分观点结合作者这几年的开发感悟,接下来总结一些关于Android App安全方面的经验。

Android App安全经验

首先明确一点,所谓的安全,只是一个相对的概念,并没有绝对的安全。对于一个App,如果黑客有足够的时间并且足够坚定,那么他就能破解所有的App,因此我们所能做的只是让App相对更加安全,或者说增加应用被破解的难度。以下经验不分先后:

  • 从代码层面加以保护,如使用混淆器混淆代码。需要注意的是选择合适的混淆器及混淆级别,同时务必在上传APK到市场之前自己反编译一下,检查代码混淆是否起到作用。代码混淆只是保证APK被反编译后看到的是无意义的代码,加大理解难度,但并不能阻止被反汇编,好在Smail理解起来要比反编译得到的代码难度大多了。但Smail也有其语法,还是可以被破解的。
  • 利用NDK,将某些关键性的逻辑或规则,如核心算法、加密规则等用C或C++来实现,这样可以大大增加代码被破的难度。但是没有绝对的安全,C或C++代码虽不能被反编译,但可以被反汇编,黑客还是可以读取二进制文件,遇到高手仍然无能为力。曾经我们App的加密算法写在C中还是被破了,也耳闻一位高手是如何破别人的算法库的,道高一尺,魔高一丈,就是这样互相博弈。
  • 对资源进行混淆,由于我们一般对资源命名有着特定规则和含义,黑客们往往由于代码混淆而不好入手时,从而改为由资源文件作为突破口。资源混淆的原理跟代码混淆类似,就是把原来有意义的命名改为无意义的命名,如home.xml变成a.xml,原来一看就知道是首页相关布局,而混淆后就加大了理解难度。
  • 对APK进行加固,目的是为了防止反编译。目前已有很多第三方的加密工具,有收费的也有免费的。如果有能力和精力,建议自己开发,使用第三方的工具,至少我个人不会放心。
  • 不要将App中的敏感信息存储在外部存储器中,因为SD卡是大家都可以访问的。最好存在App的私有目录,最完美的做法是从不在客户端保存任何数据,都存储在云端。
  • 与服务器通信时尽可能地使用HTTPS,并做真正的证书校验及主机验证,防止中间人攻击,保证数据通信安全,这样如果所有数据都在云端的话才有意义。
  • 客户端本地数据库或SharedPreferences存储关键数据时不要存储明文,估计很多应用的用户名和密码都是以明文在客户端存储的,请务必加密,关于加密密钥后文会谈到。
  • 使用已经存在的加密算法,而不要自己去写一个,已经证明过的总比未经证明的靠谱。
  • 所有的加密尽可能使用非对称加密,加密密钥最好不要保存在本地,如果保存在本地,那一定要藏得隐蔽一些,或者写入C或C++中,不过要找到也只是时间问题。
  • 对于进程间通信、广播接收、进程间隐式Intent调用,务必注意权限设置及安全防范,防止信息或数据泄露。
  • 使用SQL参数化查询,避免SQL注入。
  • WebView中如果不需要JavaScript,那么一定要禁用,以防XSS攻击。可惜的是目前大多Hybrid App都是需要JavaScript的。对于Hybrid App,一定提醒Web开发人员将JavaScript代码进行混淆。
  • 将App需要的权限需求减到最少,不要申请不必要的权限,因为权限越多,App越不安全。有一种非常好的方案是尽可能使用Intent的方式减少对权限的申请,如拨打电话,可以通过Intent调用系统拨号从而不必单独申请权限。
  • 使用第三方SDK时,务必做好调查工作,了解该SDK是否含有不安全因素,如它在后台偷偷收集用户地理位置或App关键信息,甚至做其他见不得人的事。哪怕大厂提供的SDK也不能相信,根据国内的业界情况,你懂的。可以通过第三方SDK需要的权限来初步判断,如果它需要很多与其表述的功能无关的权限,那么你就不得不留心了。如果第三库是开源的,必须通读源码,如果非开源,可以试着反编译第三方库,尝试搜索可疑字符串。
  • 做好安全验证工作,不仅仅是在客户端,也要在服务端同时做好,双管齐下。尽可能使用设备ID、设备Mac地址、设备型号品牌等信息来辅助用户名密码验证。
  • 服务端的校验工作务必做好,另外尽量避免暴露RESTful API,因为这种API规则的统一性很容易在得知一个后实施其他侵入。
  • 服务端需要根据请求数量或请求类型来决定一个单独IP的访问间隔和次数,如频繁访问则可能被认为是数据爬取而封锁该IP。
  • 服务端应当与客户端约定请求验证规则,如利用随机数机制来阻止对服务器实施重放攻击。
  • 在Android开发过程中,学会使用Lint工具,务必重视安全分类中的警告。

上述每一条经验如果细讲的话都是一个很大的话题,限于篇幅原因在此没有详细阐述实施方案,欢迎大家留言讨论。由于个人经验有限,上面列举的只是暂时想到的,必定有所遗漏,同样欢迎大家分享补充关于Android App安全的策略和方案,最后希望大家都能开发出安全的App。

2 0