网易易盾

网易易盾官方号

286篇博客

值得细读!如何系统有效地提升Android代码的安全性?

网易易盾2018-11-05 14:51

众所周知,代码安全是Android开发工作中的一大核心要素。


11月3日,安卓巴士全球开发者论坛线下系列沙龙第七站在成都顺利举办。作为中国领先的安卓开发者社区,安卓巴士近年来一直致力于在全国各大城市举办线下技术大会,为Android开发者提供最为全面深入的安全技术解读。

网易云易盾移动安全专家尹彬彬指出,安全开发能有效降低开发者维护成本

网易云易盾移动安全专家尹彬彬也受邀参加了此次会议,并做《如何提升Android代码的安全性》主题演讲。针对Android开发者,他分享了在App开发周期的各个阶段中常见的安全隐患,给出了提升Android代码安全性的建议,包括安全开发、代码加固、渠道监测、应用审计等Android代码安全技术剖析。


Android应用安全存在多重隐患


尹彬彬首先提到,Android和iOS两大操作系统占据了几乎全部移动端的市场份额,但是相比后者,缺少足够严格管控以及未能形成完善安全生态的Android系统,往往会存在很多安全隐患,给企业、开发者和用户都带来了不好的影响。


比如说:


  • 代码可逆向:客户端App的逻辑能够被轻易获取和逆向,得到代码和程序中的敏感数据;
  • 功能泄漏:客户端App中高权限行为和功能被其他未授权的应用程序调用访问;
  • 可调试:客户端App能够被调试,动态地提取、修改运行时的程序数据和逻辑;
  • 日志信息泄漏:客户端App将开发时辅助调试信息打印泄露,包含敏感参数等信息;
  • 可二次打包:客户端App可能被修改代码,重新打包发布在市场上供用户下载;
  • 密码学误用:客户端App代码中使用了不安全的密码学实现,例如固定硬编码的对称加密,ECB模式的对称加密,CBC模式中IV固定等;
  • 敏感信息泄漏:客户端App代码中泄漏敏感数据,如认证使用的共享密钥、不应被暴露的后台服务器管理地址等;
  • 通信数据明文传输:客户端App与服务器端交互的数据通过明文的通信信道传输,或者加密传输,但数据依然可以被解密;
  • ......


随着技术的不断发展升级,移动App安全防护发展到现在的阶段,也已经成功引入了“安全生态链”的概念,并出现了融入到整个App开发上线周期链中的全套安全服务,这个生态链包含了安全开发、应用审计、安全加固、渠道检测等。

  • 开发阶段:开发者应遵循移动应用的安全开发规范,使用一些成熟的安全组件,如安全键盘SDK、防劫持SDK等,此外还需要定期对客户端进行安全评估;
  • 测试阶段:采用黑盒渗透攻击和白盒代码审计的方式发现移动应用的安全缺陷及安全漏洞,降低安全风险;
  • 上线阶段:上线前使用加固、混淆等技术加固应用,提高攻击门槛和逆向的时间成本;
  • 运营阶段:监控第三方应用市场,及时发现各种盗版、钓鱼、山寨等恶意应用。


安全开发能有效降低开发者维护成本


安全开发是指在开发阶段减少安全风险,从而将安全缺陷降低到最小程度,避免后期线上运营阶段出现安全问题,但是成本较高。


安全开发生命周期(SDL)是侧重于软件开发的安全保证过程,旨在开发出安全的软件应用。其核心理念就是将安全考虑集成在软件开发的每一个阶段:需求分析、设计、编码、测试和维护。从需求、设计到发布产品的每一个阶段每都增加了相应的安全活动,以减少软件中漏洞的数量并将安全缺陷降低到最小程度,尽可能地在产品版本回归前清除漏洞。


尹彬彬表示,在这一阶段,一方面可以开展SDL培训,强化安全开发意识,制定安全编码规范;另一方面是使用较成熟的安全组件。


具体的安全建议包括有:


  • 安全键盘:/dev/input/event可以读取到按键和触屏,实现安全键盘随机布局;
  • 密钥安全:避免硬编码密钥在代码中,可以本地分段加密存储,也考虑使用白盒密钥;
  • 通信安全:中间人攻击,证书弱校验等造成通信协议被分析破解,需要对通信数据加密校验和证书有效性校验;
  • 防界面劫持: Activity、对话框或者恶意悬浮窗劫持,导致用户被钓鱼或者误接触,需要防劫持;
  • 坏境监测:ROOT、模拟器、是否有恶意应用等坏境检测,Xposed插件、HOOK、调试器检测
  • 数据校验:签名校验,最好实现在jni层,多点检查、隐蔽调用位置,或者结合网络校验,检测APK中文件是否被篡改,数据指纹;
  • 重点逻辑转移到jni层实现:对重要逻辑从java层转译到jni层实现,结合代码混淆,提高分析难度;
  • 防日志泄露:防止开发日志泄露,通过开关控制,Java层通过proguard配置;
  • 防敏感数据泄露: 避免敏感数据明文保存,考虑本地存储加密(sharepreference、sqlite等);
  • 正确使用密码学算法:Hash算法使用SHA-256代替MD5,AES不要使用ECB模式,初始化向量IV不要使用固定的常量,使用/dev/urandom或者/dev/random来初始化伪随机数生成器,从而代替SecureRandom。


在开发阶段、测试阶段发现或者预防安全隐患成本较低,上线阶段或者运营阶段出现安全问题的成本较高,因此,开发者应明确安全开发的重要性。


应用审计


“只要是人在开发代码,就会存在安全漏洞”,尹彬彬如是说。近几年来,安全漏洞的形式越来越多种多样,拒绝服务、Webview明文存储密码等漏洞深切困扰着企业和开发者。因此,应用审计的重要性也越来越显著。

一般而言,应用审计的方式主要包括漏洞扫描和渗透测试。


1. 漏洞扫描


在漏洞扫描中,黑盒测试是比较常见的手段之一,也方便集成到现有的开发流程中。它能够很方便地提供漏洞详情、漏洞代码行数、风险等级、修复建议等。自动化移动应用安全测试框架Mobile Security Framework就是个很好的工具。

2. 渗透测试


渗透测试可以有效检测客户端程序安全、敏感信息安全、密码软键盘安全性、安全策略设置、手势密码安全性、通信安全、配置文件、拒绝服务、本地SQL注入等威胁类型。

代码加固


代码加固主要包括应用加固(DEX文件、SDK文件、SO文件)和源码混淆(Java、C/C++、JavaScript/HTML)两种常见手段。


1. DEX加固


从Java到C++语言,越往底层走,系统的粒度就越来越细(文件、方法、指令),壳逻辑与被加固的业务逻辑边界也越来越模糊。所以要想获得安全性和执行效率的平衡点,就可以采用DEX加固的方式。

  • 内存加载:防止静态分析;
  • 指令抽取:增大内存Dump的难度;
  • VMP保护:指令虚拟机保护;
  • Java2C:将Java指令转换为C执行。


2. SDK加固


Java字节码较容易被反编译,拿到SDK基本等于直接获取了源码。目前针对SDK的保护仅限于开发阶段的Proguard混淆,没有较高强度的安全保护措施。


但可以借用Dex加固的思想,对Java字节码做抽取处理:

3. SO加固


SO加密包括自定义节加密和自定义Linker,如下的例子所示:

  • 先确定ELF文件,即构建被加壳SO文件soinfo,再进行重定位修复:
  • 导入函数地址,获取并修复(将被加壳SO导出函数映射到壳SO),运行init_proc和init_array;
  • 修复被加壳SO文件,有效导出函数、JNI_ONLOAD函数;
  • 运行被加壳SO Jni_Onload函数。


4. Java源码混淆


此方式下可以设置自己的字典,这也是最常用的安全防护手段之一。

5. C/C++混淆


C/C++混淆可利用Obfuscator-LLVM工具高效实现,主要包括以下方法:


  • 控制流平坦化:在不改变源代码功能的前提下,将C、C++等语言中的if、while、for、do等控制语句转化为switch分支选择语句。控制流平坦化有点像虚拟机保护,case块相当于vm的handle,case值相当于vm的opcode。
  • 指令替换:生成条件跳转指令有两种方法,一种称为opaque predicate,另一种称为bogus control flow。假设基本块block0,opaque predicate后变为:if(恒等式){block0;}else{垃圾代码}或if(恒不等式){垃圾代码}else{block0;};bogus control flow后变为if(随机条件){block0;}else{block1;},else的基本块block1复制于block0。
  • 控制流伪造。


其他常见的C/C++混淆手段还有:


  • 多重分支;
  • 基本块分割:把基本块分成多个基本块。有两种方法:一种是根据概率对基本块的当前指令进行分割;另一种是计算基本块的总指令数,标记为a,随机生成小于a的数,标记为b,基本块b条指令后进行分割,a减掉b,进行多次迭代直至a等于1。
  • 字符串加密;
  • 常量隐藏;
  • 常量展开;
  • 常量数组随机化:让常量在数组中的索引随机化。假设常量数组a[],索引值i,随机生成索引数组b[]、c[]、d[](可生成更多),循环用z[b[c[d[i]]]]=a[i]生成随机后的常量数组z[],然后用z[b[c[d[i]]]]替换a[i]。
  • 表达式变换:对逻辑操作not、and、or、xor,可以先把操作数抽取分成多个更小的数进行操作,最后用or连接起来,当然这四个操作可以用与非门或是或非门来完成。还有其它常见的运算可以把操作数看成大数然后进行大数运算,还有一些运算可以转变为SIMD指令进行运算。至于浮点数,有很多浮点数的软件实现可供参考。


6. H5混淆


H5混淆是指从JS的语法和逻辑上进行混淆。


这种是从抽象语法树角度对JS的源码进行语法分析,将源码字符串转换为树形结构,然后对相应的属性(如字符串、变量名、函数名等)进行混淆或加密。

渠道监测能够随时感知安全态势


渠道监测也是Android安全开发中的一个重要课题,其工作内容主要是App是否被调试、HOOK、脱壳等运行时信息的上报,以便随时感知安全态势。


  • 爬虫:监测主流渠道应用下载数据,包括第三方市场、论坛等;
  • 盗版识别:应用图标、名称、包名、资源文件、代码指纹等,使用相似度算法分析;
  • 数据分析:盗版渠道分布、下载量、盗版溯源、篡改内容等数据分析。

总结


“攻防没有止境”,尹彬彬表示,通过安全编码规范要求、上线前的安全检测、代码加固、业务运行中基于网络通信层的完整性校验、标准化的SDL检测等全方面的安全防护,能够抵御8-9成的攻击,但是还是有可能会有新的安全问题出现。

因此,他指出:“移动安全的方案需要更加贴合业务层面,与时俱进”。


网易云易盾依托网易20年的技术积累及对数十条业务线的保障经验,拥有海量特征库和成熟的安全机制,并结合超强云计算及人工智能技术,形成对游戏、金融、电商、娱乐等场景化解决方案,服务集团内外上千家客户。“如果需要获得更加可靠的移动安全保障,可以来和我们聊聊。”尹彬彬最后表示。


点击免费体验网易云易盾移动安全解决方案