安卓安全那点事
Posted xjz729827161
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了安卓安全那点事相关的知识,希望对你有一定的参考价值。
本文旨在对于一个安卓app的安全知识做一个较为泛泛的总结,为开发出更安全的应用提供思路。内容比较粗略,仅起到抛砖引玉的效果,还望大家见谅。
android应用的安全
意义
在维基百科上有一个关于计算机安全的定义:
计算机安全(computer security)是计算机与网络领域的信息安全(information security)的一个分支。其目的是在保证信息和财产可被授权用户正常获取和使用的情况下,保护此信息和财产不受偷窃,污染,自然灾害等的损坏。计算机系统安全是指一系列包含敏感和有价值的信息和服务的进程和机制,不被未得到授权和不被信任的个人,团体或事件公开,修改或损坏。由于它的目的在于防止不需要的行为发生而非使得某些行为发生,其策略和方法常常与其他大多数的计算机技术不同
这些话中,关键点是 保护, 信息和财产。现如今的信息是有价值的,是财产的一部分,应用的保护说到底是就保护自己的财产。合理有效的防护手段能够避免自身的利益受到损害。
现状
关于这件事,Android从业人员做的怎么样呢?从腾讯的安全科恩实验室的报告中做了一个截取
看报告的结论只能说惨不忍睹,差点就全军覆没了。安卓从业人员这安全意识这一块做的不怎么好,甚至连安全意识都没有的人也大有存在。根据我的开发经历开看,不少开发人员对安全这块可以说是一无所知
讲两个我遇到的真实案例
- 曾经的就职的某手机公司,早期系统应用的签名都是统一的,人手一个是一个非常廉价的可获取资源。后来发生了一件事,有一个消费者投诉反馈到了工信部,经调查发现系统的浏览器被插入了一些不可描述的广告。很不幸的是被注入的页面是我提供的SDK,虽然锅没有背在我的身上,但是这个事情相关联的人都受到较为严格的处罚
- 公司邀请专业的安全公司顾问上门给我们进行科普,这些安全人员就针对公司应用的安全扫描中,结果发现了一些应用的超级权限有弱口令像12345这样的可以直接进行访问,用户设置的密码如同摆设,一度场面十分尴尬。很多应用用裸奔来形容也不为过
如何破解一个APP
情景假设:给你一百万如果针对一个应用或者体系获取需要的的信息
古语云:上兵伐谋,其次伐交,再次伐兵
- PlanA: 直接收买开发人员
- PlanB: 收买开发人员的手中的部分信息,然后再招人破解
- PlanC: 直接硬刚一波进行破解
以上的三个策略PlanA是最佳的,因为获取信息最全面,成本也最低,但是风险确较高。
虽然PlanC的硬刚破解是最笨的办法,但是我们做技术的需要研究的也就是这种最笨拙的方式了。以上的例子只是为了告诉大家
安全的本质是成本,如果可以,技术的手段是非必须的
安全的成本本质也体现在防守的一方,做防守的人也需要在安全成本的投入上进行衡量。防守策略的投入,会使得应用的不稳定因素提高,启动变慢,体积变大,用户的操作受到影响等隐性成本的提升。
有点跑题了,回归技术的相关,破解一个应用的基本思路
- 采集信息(日志信息,网络报文,落地的文件,使用的类库等)
- 分析数据(寻找加密算法,分析数据报文的真实内容)
- 验证数据
- 伪造数据或者篡改应用本身
这里最难的是第一二步,后面的大多有可以直接抄袭的实现代码,反而比较容易。采集信息就是见缝插针,尽可能的了解更多。
知己知彼方能百战不殆,回顾一个软件产品的上线过程,了解每一个细节,才能去找寻可能的漏洞。
一个软件的正常流程是这样的:
设计->开发->发布->运行
设计安全
设计上的分类分为UI设计安全 和 业务逻辑设计安全
UI设计安全
在UI操作上防止泄露必要的信息,虽然基础但是很有必要
比如登录的账号密码,在显示时会增加一个密码的隐藏过程
这里就包含好几点可以进行处理,
- 界面上不会显示明码防止窥屏
- 界面上显示的黑色点数并不是真实的位数,防止通过位数来猜测
- 使用系统级别安全的键盘或者自定义键盘输入
- 禁止残障人员辅助功能
- 隐私信息的后台模糊显示
逻辑设计安全
对于设计的业务逻辑应该是一个完整的闭环,对于攻击应该有意识的进行应对。
身为应用的门户,登录是所有人应对的第一关。不知道大家是否发现登录这个环节无论是在哪个应用中都算是比较奇葩的,有很多在登录时做的验证操作,短信验证人脸识别等等,这些操作的初衷是为了什么?
同样是提问:
- 登录是单点的么?
- 登录需要怎么识别是非机器操作?
- 登录需要超时么?
- 登录的出错尝试的多少次?
- 登录的出错验证需要什么进行处理?
一个完整的业务逻辑是需要考虑要考虑为了安全需要做到哪一步的?在用户使用的便宜性和安全级别之间做衡量。设计的东西太繁杂,需要在设计阶段就需要细细的琢磨,不能太过随意
这里吐槽一点,就是网易大师邮箱的登录,没法设置单点,也没放弃某一个客户端的登录,登录了多个邮箱后,旧的邮箱仍然在不断的推送。如果暂时把登陆过的设备出借他人了,没有任何办法知道我的信息到底分发到哪里去了,差评。
源码安全
项目管理级别
-
源文件下载的管理
代码的下载管理,ssh下载优于账号密码的下载
使用电脑的文件加密(usb口限制了) -
code Review
代码安全的审核,防止溢出等导致可能的攻击
依赖库的审核 (比如fastjson又双叒叕暴露了高危漏洞)
sonar的静态检测工具是也是有必要的 -
秘钥管理
秘钥是身份证,不要身份证人手一张,影响不好,最理想的状态是除了管理层应该谁也不知道签名的秘钥
jekins gitlab 上面都可以支持参数配置,脚本运行打包的方式
源码自身的保护
- 文件混淆 资源混淆
-
守
文件混淆和资源混淆的意义都在于降低其代码的可阅读性。增加反向阅读的难度。
一般情况下资源是不用混淆的,出于做到更优的想法,资源的隐藏比没有隐藏肯定会更好。
资源混淆是一个比较复杂的操作,目前看到是腾讯系的使用比较多。
目前android使用的ProGuard的工具进行class文件的混淆操作,这里仍然提醒的一点是混淆是颗粒度,较多的开发者对于proGuard的工具没有清晰的认识,只会最简单的处理方式。对于安全级别高的应用,应该尽可能的做多的混淆
处理前,
处理后
-
源码阅读工具
阅读class的工具jd-gui下载地址
github新出项目的比较好用的一键解读apk的神器 jadx附上对应的github地址
如果前两者的转换有不全面的,借助baksmali 则可以直接转smali后进行阅读,smali类似于汇编语言的存在,如果到了这个级别,我就根本不在乎字节码的可读性了,因为本身就可读性很差了。
-
静态保护 加花指令,防止静态分析工具,比如针对.so分析的IDAPro
class的字节码世界已经不安全了,我要进行进一步的隐藏,内容下沉到.so中。
(ps:我们公司的使用的易盾就是有这种操作)
代码下沉后,仍然有比较好用工具比如IDApro这类静态分析工具能够进行阅读。
这个时候我们可以加入适当的花指令
花指令有两种表现方式:- 一种是无用的代码增加你的阅读量
- 一种是陷阱指令使得的反编译工具在运行时出现问题或者不能正确的解析一些真实的代码
-
动态保护 加固,隐藏真实的内容
加壳的程序可以有效阻止对程序的反汇编分析,以达到它不可告人的目的。这种技术也常用来保护软件版权,防止被软件破解
在不同的平台上涉及到具体的操作手段会有所区别,但本质上都有壳程序优先获得应用的控制权,代替系统的加载过程,完成自定义的加载。在加载的过程中可以有加解密的操作,达到隐藏源码的作用。
运行时安全
- 简单的自证身份
-
守
签名的合法性进行校验防止二次打包的应用 -
攻
篡改函数的返回值
二次打包后可以任意的注入代码
- 数据传输安全
你还在用http嘛?https一定是安全的嘛?
一句话描述https: https的本质是通过非对称的加密方式保护对称秘钥的传输
在实际的场景中由几种app使用Https的方式
1、信任任何证书
2、信任系统校验证书
3、公钥校验
4、证书全校验
-
守
正确的使用https
单端校验的完善(https中需要校验主机名等操作)
最理想的是双端校验,服务器需要校验客户端的合法性,客户端也需要校验服务器的合法性
同时也可以不信任代理,拒绝代理等方式来保护通信 -
攻
使用flidder主要针对是http/https的报文
wireshark则主要是直接抓取的网卡的数据,更加的全面强大
- 数据落地安全
- 守
日志不明码
文件寻找合适的存储位置(android的存储位置为应用内部私有空间,应用外部私有空间,应用外部公共空间)
文件落地加密
数据库落地加密 - 攻
root权限,获取所有的文件
查看应用找到加密算法和秘钥
- 组件通信安全
与SQL注入类似,Android中四大组件暴露的组件是很危险的Activity ContentProvider, Service, Broadcast
- 攻
获取不同的报文猜测应用的行为
针对ContentProvider也可以进行注入 - 守
- 隐藏不必要的组件
- 组件的输入参数进行严格的校验
- 所有涉及到跨进程传递的,只能是加密的敏感数据或者非敏感数据
- 反调试
-
攻
应用二次打包,调整清单文件debugable为可调试
系统全局系统设置为可调试 ro.debuggable 1
apk->smali文件进行调试
XPosed , Magisk或者 VirtualAPP hookAPI
XPosed操作:system/bin/下面的文件替换了app_process等文件,app_process就是zygote进程文件。所以Xposed通过替换zygote进程实现了控制手机上所有app进程。因为所有app进程都是由Zygote fork出来的。
Xposed的基本原理是修改了ART/Davilk虚拟机,将需要hook的函数注册为Native层函数。当执行到这一函数是虚拟机会优先执行Native层函数,然后再去执行Java层函数,这样完成函数的hook。
-
守
- 调试检测,根据自身的编译检测调试环境
每个进程同时刻只能被1个调试进程ptrace,再次p自己会失败。所以可以主动ptrace自己,根据返回值判断自己是否被调试了 - 进程名检测
- 系统的调试检测函数
- 断点搜索的检测(软断,硬断,内存断)
- 调试检测,根据自身的编译检测调试环境
-
检查虚拟机环境
- 检查手机IMEI等一系列编号
- 读取手机品牌信息
- 检查mac地址
- 处理器信息
-
检查Xposed 框架
- 遍历App安装列表检测
- 通过自造异常检测堆栈信息,读取异常堆栈中是否包含Xposed字符串来识
- 通过ClassLoader的 loadClass 加载列表检测
- 由于Xposed的注入方式是通过底层SO文件修改被hook的方法为native来实现的,所以检测方也可以通过检测方法是否变成了native来达到检测的目的
- 检测Xposed相关文件
- 通过反射XposedHelper类和XposedBridge类做信息检测
结语
安全领域是一个庞大而专业的领域,身为非专业的人员很难到做精通,但是对其有所了解是非常有必要的事情。避免一些低级的错误,是我们作为一个合格的开发人员应该具备的素质。能够尽可能的了解安全的知识,才能做出一个靠谱的产品。
你没法赚到超出你认知范围外的钱,同样你也没法做出你认知范围外的防守。
共勉!
以上是关于安卓安全那点事的主要内容,如果未能解决你的问题,请参考以下文章