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

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

相关文章:
【推荐】 数据仓库的直白概述
【推荐】 Docker容器的原理与实践(上)

值得细读!如何系统有效地提升Android代码的安全性?的更多相关文章

  1. 从Android系统出发,分析Android控件构架

    从Android系统出发,分析Android控件构架 Android中所有的控件追溯到根源,就是View 和ViewGroup,相信这个大家都知道,但是大家也许会不太清楚它们之间的具体关系是什么,在A ...

  2. 10 条提升 Android 性能的建议

    About the Speaker: Boris Farber 每个人都知道一个 App 的成功,更这个 App 的性能体验有着很密切的关系.但是如何让你的 App 拥有极致性能体验呢?在 Droid ...

  3. 【转】10 条提升 Android 性能的建议

    每个人都知道一个 App 的成功,与这个 App 的性能体验有着很密切的关系.但是如何让你的 App 拥有极致性能体验呢?在 DroidCon NYC 2015 的这个分享里,Boris Farber ...

  4. Mac系统下编译支持Android平台的最新X264编码器

    Mac系统下编译支持Android平台的最新X264编码器 原文来自 http://www.mingjianhua.com,转载请注明出处 1.首先去官网下载最新的x264源代码,解压到任意目录 ht ...

  5. 将Android系统源码导入Android studio的方法

    Android源码目录结构如下: |-- Makefile|-- abi (applicationbinary interface,应用程序二进制接口,生成libgabi++.so相关库文件)|-- ...

  6. android API版本对应的系统版本及Android获取手机和系统版本等信息的代码

    学了这么久的Android,竟然一直对其API对应的名称关系一值搞不清楚,现在网上认真看了下资料,转载一个觉得写得不错的作者的文章,记下来: [背景] 之前折腾android期间,慢慢地知道了,And ...

  7. 【系统之音】Android进程的创建及启动简述

    Android系统中的进程(这里不包括init等底层的进程)都是通过Zygote fork而来的,那这些进程的启动流程都是怎样的呢? 这里将Android进程分为两个部分: (1)系统框架进程Syst ...

  8. 编写高效的Android代码

    编写高效的Android代码 毫无疑问,基于Android平台的设备一定是嵌入式设备.现代的手持设备不仅仅是一部电话那么简单,它还是一个小型的手持电脑,但是,即使是最快的最高端的手持设备也远远比不上一 ...

  9. Android代码内存优化建议-OnTrimMemory优化

    原文  http://androidperformance.com/2015/07/20/Android代码内存优化建议-OnTrimMemory优化/ OnTrimMemory 回调是 Androi ...

随机推荐

  1. 蓝桥杯 算法训练 ALGO-151 6-2递归求二进制表示位数

    算法训练 6-2递归求二进制表示位数   时间限制:10.0s   内存限制:256.0MB 问题描述 给定一个十进制整数,返回其对应的二进制数的位数.例如,输入十进制数9,其对应的二进制数是1001 ...

  2. HDU4039(map应用)

    The Social Network Time Limit: 3000/2000 MS (Java/Others) Memory Limit: 65768/65768 K (Java/Others)T ...

  3. (转)红帽 Red Hat Linux相关产品iso镜像下载【百度云】【更新6.7 Boot Disk】

    不为什么,就为了方便搜索,特把红帽EL 5.EL6 的各版本整理一下,共享出来. RedHat Enterprise Server 6.7 for i386 Boot Disk:rhel-server ...

  4. L2-014. 列车调度(set的使用,最长递增子序列)

    L2-014. 列车调度 时间限制 300 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 火车站的列车调度铁轨的结构如下图所示. Figure ...

  5. Eloquent ORM模型中添加自定义值

    我们都知道通过Laravel中数据库查询出来的模型对象都是基于数据库字段,今天给大家展示一个 Laravel Eloquent ORM 模型特性-附加值不存在于数据表中. 举个简单的栗子,一篇文章(p ...

  6. CSS——position

    position是指元素的定位方式,有:static.absolute.fixed.relative.inherit 5种. static 默认,布局排版方式按照HTML代码的顺序布局. absolu ...

  7. javascript——对象的概念——内建对象

    包括内建对象的所有对象都是Object对象的子对象. 1.Array():构建数组的内建构造器函数 例:创建数组方式有两种: 2.Boolean:是对象,与基本数据类型 布尔值 不相同 例:创建Boo ...

  8. Django之时区

    在settings.py中修改如下配置: TIME_ZONE = 'Asia/Shanghai' USE_I18N = True USE_L10N = True USE_TZ = False 这样在m ...

  9. 1-EasyNetQ介绍(黄亮翻译)

    EasyNetQ 是一个容易使用,坚固的,针对RabbitMQ的 .NET API. 假如你尽可能快的想去安装和运行RabbitMQ,请去看入门指南. EasyNetQ是为了提供一个尽可能简洁的适用与 ...

  10. eclipse 报错:GC overhead limit exceeded

    还是eclipse内存问题 修改eclipse.ini -Xms512m -Xmx1024m 必要的情况下, 添加 -XX:MaxPermSize=1024M  表示在编译文件时一直占有最大内存