cover_image

Android安全知识浅谈

良宏 玩物少年们
2021年03月09日 02:00

本期内容

  • 背景
  • 实践
    • 程序安全
    • 数据安全
    • 风控保障
  • 总结


一、背景

     近几年随着网络信息技术迅速发展,移动互联网的生态系统日益庞大,市场上丰富的移动应用也越来越多,在手机APP为我们提供便捷服务的同时,木马病毒程序破解广告钓鱼信息窃取二次打包等诸多移动端安全问题也一直环绕着我们,若对应用中潜在的安全隐患不能够及时发现和处理,一旦出现问题,无论是对公司或用户,都将受到不可估量的伤害。

     2019和2020年是玩物得志高速发展的两年,随着公司的体量越来越大、用户数日益增多,APP工程体积也逐渐庞大,但早期APP应用在安全方面的建设较为薄弱,我们同样面临着这些安全隐患,导致应用程序被破解、核心代码被窃取、API接口被伪造/篡改、黑产用户虚假注册、批量刷单/薅羊毛、推广作弊群发广告等一系列问题,给公司带来了不小的经济损失。


二、实践

     移动端安全问题主要体现在3个方面:程序的安全 + 数据的保护 + 风险的保障

     如果程序本身被攻击者破解,则会导致隐私数据、关键代码逻辑泄漏,进而攻击者可非法获取到用户的私有数据或伪造各种数据请求;若服务端真正面来自对虚假终端的攻击,自身也需要有风险鉴别和保障的能力。因此我们主要从APP程序本身安全、数据通信安全、后端风控保障等几个方面入手,逐步提升玩物得志APP的安全等级。

图片

2.1、程序安全

2.1.1、程序漏洞

  • AllowBackup漏洞
         Android2.1以上的系统可以为APP提供应用程序数据的备份和恢复功能,当AndroidManifest.xml文件中的allowBackup被设置为true时,攻击者可通过adb backup、adb restore来对应用数据进行备份和恢复,从而获取到用户的敏感信息,如证件号、手机号、身份令牌等,造成用户隐私数据的泄漏和资产损失,这里显式设置为false,不能对应用数据备份。

<application    android:allowBackup="false"    tools:replace="android:allowBackup">


  • Java动态调试风险
         应用级配置文件build.gradle中的调试标记默认是true,即可以被Java调试工具如JDB进行调试,这样存在攻击者获取和篡改用户敏感信息,甚至分析并且修改代码实现的业务逻辑,从而窃取用户密码、绕过验证码防护等实现一些违规操作,在正式发布应用之前,需要设置android:debuggable属性为false,关闭Java动态调试功能,不允许被调试。

buildTypes {    release {        debuggable false//调试        minifyEnabled true//混淆    }}


  • 程序包日志控制
         一些开发者习惯于在开发过程中打印调试日志,用于排查问题,却没能在调试完毕后及时删除日志。调试函数日志中可能输出重要的调试信息,诸如组件名、通信数据、跟踪变量等,这些信息的打印会导致用户信息、重要代码事件流的泄漏,从而为攻击者提供便利。对应用内Log统一封装控制基类,并判断测试环境允许打印日志,正式环境关闭日志的输出,或修改编译器配置,对敏感代码进行Inspections提醒,告知开发者应做到及时删除。


  • WebView数据隐患
         安卓WebView组件默认开启了密码保存功能,会提示用户是否保存密码,这些数据会被明文保存到应用数据目录的databases/webview.db中,攻击者可通过root的方式访问该应用的WebView数据库,从而窃取本地明文存储的用户名和密码。我们通过设置savePassword()为false来显式关闭密码存储功能。

WebView.getSettings().setSavePassword(false);
  • 应用组件暴露
         Activity、Service、Provider、Receiver四大组件若配置为android:exported=true,将可以被外部应用调用,这样会存在安全隐患,攻击者可以通过外部传入Intent来越权访问,从而引起数据泄露、DOS攻击和应用连续崩溃等问题。因此我们根据最小化组件暴露的原则,就路由方面,进行统一的入口收拢和安全校验,通过来源验证、路由白名单、开关控制、降级处理、异常引导等多重策略,形成一条安全的路由调用链路。

图片


2.1.2、代码混淆

     开启代码混淆minifyEnabled=true,有利于增加攻击者反编译获取代码的成本,且打包时移除无用资源,减少 APK 体积;

    • 代码缩减从应用及其库依赖项中检测并安全地移除不使用的类、字段、方法和属性;

    • 资源缩减从封装应用中移除不使用的资源,包括应用库依赖项中不使用的资源;

    • 代码混淆缩短类和成员的名称,使用无规则字母代替,减小 DEX 文件的大小;

    • 代码优化检查并重写代码,优化目标语法,进一步减小应用的 DEX 文件的大小;

     引入资源混淆如AndResGuard,将原本冗余的资源路径变短,如“res/drawable/newerIcon”将变为“r/d/i”,可以再次优化减Apk体积,且混淆资源路径后,使用ApkTool工具无法直接回编生成二次APK,也在一定程度上提升了APK反破解难度;

图片


2.1.3、应用签名

     应用签名在保障设备安全方面发挥着重要作用,可用于进行权限检查以及软件更新。

     签名一是保证消息来源的真实性,二是确保消息不会被第三方篡改,早期的V1签名会将APK内文件进行逐一签名并将签名结果保存在ETA-INF目录下,V1签名的缺点一是签名校验速度较慢,在APK安装校验过程中需要对所有文件进行摘要计算,在APK资源较多、性能较差的机器上签名校验将花费较长时间,导致安装速度慢,影响用户体验,且META-INF目录用来存放签名,自然此目录本身是不计入签名校验过程的,可以随意在这个目录中添加文件。

     我们升级到V2版本签名,V2签名将验证归档中的所有字节,而不是单个ZIP条目,因此在签署后无法再运行重压ZIP包等,能够及时发现对APK的受保护部分进行的所有更改,从而有助于加快验证速度并增强完整性保证。(后续Android9.0引入了V3版本签名,在V2插入的签名块中又插入了一个新块,以秘钥轮转的方案,来做签名的替换和升级)

图片

图片


2.1.4、APK加固

     普通的APK文件对攻击者来说属于裸奔状态,被反编译后能够轻易得到明文资源和dex原代码文件,因为常规的Android程序代码都将打包在dex和so文件中,这些文件经过反编译工具可以得到对应的源代码阅读。应用加固技术可以将原dex文件加密或者隐藏起来,放入一个新的壳dex到到APK中,程序启动时先运行这个壳dex,然后壳dex在运行时再加载原dex,使得攻击者不能直接通过APK解压轻易获取到原代码资料。

     我们通过引入第三方加固平台对混淆签名后的APK进行安全加固,从而进一步保证dex、so、资源文件、数据文件等重要的APK文件信息的安全性,加固后的APK通过代码插花、虚假控制流、字符串加密等手段提高了程序被破解的难度,能够一定程度上防止静态逆向、防篡改和二次打包,有效保护APP的安全性。

图片


2.2、数据安全

     数据安全包括 网络数据 和 本地数据 两个方面。早期的Http协议是明文传输,攻击者可以轻易的通过Charles或Fiddler等抓包工具来拦截和篡改请求数据,虽然Android9.0以后谷歌官方限制了默认不允许非加密的链接来改进对设备和数据安全的保护,但是Https并不能直接阻挡攻击者分析请求接口并发起恶意请求攻击,数据之间的传递仍可被攻击者轻易抓取到并进行篡改。

2.2.1、网络数据

  • 昆仑网关
    对于终端之间的通讯的数据安全,主要存在3个问题:
    1. 传输内容可能被窃听;

    2.传输内容可能被篡改;

    3.无法验证双方的身份;

  • 为了保证数据的真实性和可靠性,一般通过加签加密2种方式来提高数据交互的安全性;

    • 签名校验:对请求数据、请求头参数进行一定规则的拼接和运算并进行结果签名,生成唯一的结果sign作为校验字段,服务端接收到请求后进行唯一性验签校验,至于签名规则可双方约定,这里的签名规则相当于秘钥的作用,可将签名代码Native化,或增加花指令来进一步提高破解难度。

    • 数据加密:Post到服务器和从服务器接收到的数据都应进行加密后再传输,至于加密类型有多种手段,一般使用对称加密和非对称加密的混合方式进行,毕竟对称加密的耗时较大,对大数据加密时存在一定的性能问题,Https本身的加密处理也是类似。另外可以由后端控制公钥的过期时间和刷新来保持秘钥的动态性,进一步提高安全等级。


网关的接入
     我们通过接入统一的API网关层,对所有业务接口进行前置的网关预处理,如用户鉴权安全策略接口限流链路追踪等,封装标准化请求头、通用入参出参、请求签名、数据加解密、拦截器处理等一系列功能,通过网关层的统一控制,增强工程的稳定性和数据安全性。

图片


2.2.2、本地数据

     数据库、SP文件、本地日志、资源文件

     本地数据包括存储在本地的接口缓存数据、用户登录信息、开关配置、本地Log日志等,其中不免也会包含到用户隐私数据或重要的程序运行信息,当应用程序被破解或设备处于root环境下,本地沙盒数据将完全暴露出来,同样存在数据泄露的风险。

     因此,应用本地数据同样需要酌情进行加密存储,如Sqlite数据库、SP文件、SD卡缓存、程序运行日志、本地资源文件等,加密过程可根据数据重要程度进行对称加密或非对称加密,且同样建议将加密过程Native化,相对于Java代码容易被反编译,C++代码编译后生成的库是一个二进制文件,能够初步阻挡住一些逆向者。

图片


2.3、风控保障 

     环境监测、设备指纹、风险控制

     电商交易流程中,诸多环节可能被黑产用户通过一些自动化工具完成,如营销活动作弊/薅羊毛、虚假用户裂变、直播刷榜单、登录/支付环境、内容爬取等,强占商家优质资源,损害商家和用户的双向利益,且服务端难以辨别对方属于真实用户还是虚假身份。

     一般我们通过自研和接入第三方风控服务来逐步完善我们的风控体系,从账号风控、通用风控、垃圾识别几个方面,通过设备指纹上报、终端运行环境监测、模型训练、特征清洗、综合分析,从业务/接口/用户/设备等多维度的风控判断,进行虚假设备鉴别和过滤以及风险行为的拦截。

图片


三、总结

安全性在移动互联网领域从来都是一个不容小视的问题,经过APP程序方面的问题治理和后端风控体系的建设,我们进一步提升了应用的安全等级,在一定程度上提高了攻击者的门槛,线上风控方面的各种建设也为公司节省了约30%由黑产攻击者带来的资产损失。

移动端安全攻防是个长久的话题,做好应用体系的安全策略、让应用更安全更可靠的运行,是每个开发者义不容辞的责任,我们也会持续关注各个方面安的全相关问题,通过不断加强技术手段,提高玩物得志代码和应用的安全质量。



牛年邀牛人

一起战斗、一起成长

技术、产品、UED、运营、职能等海量岗位

玩物得志期待你的加入

图片


Android · 目录
下一篇Android网络图片加载优化
继续滑动看下一个
玩物少年们
向上滑动看下一个