安卓安全那点事

本文旨在对于一个安卓app的安全知识做一个较为泛泛的总结,为开发出更安全的应用提供思路。内容比较粗略,仅起到抛砖引玉的效果,还望大家见谅。

Android应用的安全

意义

在维基百科上有一个关于计算机安全的定义:

计算机安全(computer security)是计算机与网络领域的信息安全(information security)的一个分支。其目的是在保证信息和财产可被授权用户正常获取和使用的情况下,保护此信息和财产不受偷窃,污染,自然灾害等的损坏。计算机系统安全是指一系列包含敏感和有价值的信息和服务的进程和机制,不被未得到授权和不被信任的个人,团体或事件公开,修改或损坏。由于它的目的在于防止不需要的行为发生而非使得某些行为发生,其策略和方法常常与其他大多数的计算机技术不同

这些话中,关键点是 保护, 信息和财产。现如今的信息是有价值的,是财产的一部分,应用的保护说到底是就保护自己的财产。合理有效的防护手段能够避免自身的利益受到损害。

现状

关于这件事,Android从业人员做的怎么样呢?从腾讯的安全科恩实验室的报告中做了一个截取
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aqcBKZGd-1593566519763)(./images/1590722564509.png)]

看报告的结论只能说惨不忍睹,差点就全军覆没了。安卓从业人员这安全意识这一块做的不怎么好,甚至连安全意识都没有的人也大有存在。根据我的开发经历开看,不少开发人员对安全这块可以说是一无所知

讲两个我遇到的真实案例

  • 曾经的就职的某手机公司,早期系统应用的签名都是统一的,人手一个是一个非常廉价的可获取资源。后来发生了一件事,有一个消费者投诉反馈到了工信部,经调查发现系统的浏览器被插入了一些不可描述的广告。很不幸的是被注入的页面是我提供的SDK,虽然锅没有背在我的身上,但是这个事情相关联的人都受到较为严格的处罚
  • 公司邀请专业的安全公司顾问上门给我们进行科普,这些安全人员就针对公司应用的安全扫描中,结果发现了一些应用的超级权限有弱口令像12345这样的可以直接进行访问,用户设置的密码如同摆设,一度场面十分尴尬。很多应用用裸奔来形容也不为过

如何破解一个APP

情景假设:给你一百万如果针对一个应用或者体系获取需要的的信息

古语云:上兵伐谋,其次伐交,再次伐兵

  • PlanA: 直接收买开发人员
  • PlanB: 收买开发人员的手中的部分信息,然后再招人破解
  • PlanC: 直接硬刚一波进行破解

以上的三个策略PlanA是最佳的,因为获取信息最全面,成本也最低,但是风险确较高。

虽然PlanC的硬刚破解是最笨的办法,但是我们做技术的需要研究的也就是这种最笨拙的方式了。以上的例子只是为了告诉大家
安全的本质是成本,如果可以,技术的手段是非必须的

安全的成本本质也体现在防守的一方,做防守的人也需要在安全成本的投入上进行衡量。防守策略的投入,会使得应用的不稳定因素提高,启动变慢,体积变大,用户的操作受到影响等隐性成本的提升。

有点跑题了,回归技术的相关,破解一个应用的基本思路

  1. 采集信息(日志信息,网络报文,落地的文件,使用的类库等)
  2. 分析数据(寻找加密算法,分析数据报文的真实内容)
  3. 验证数据
  4. 伪造数据或者篡改应用本身

这里最难的是第一二步,后面的大多有可以直接抄袭的实现代码,反而比较容易。采集信息就是见缝插针,尽可能的了解更多。
知己知彼方能百战不殆,回顾一个软件产品的上线过程,了解每一个细节,才能去找寻可能的漏洞。

一个软件的正常流程是这样的:
设计->开发->发布->运行
在这里插入图片描述

设计安全

设计上的分类分为UI设计安全业务逻辑设计安全

UI设计安全

在UI操作上防止泄露必要的信息,虽然基础但是很有必要
比如登录的账号密码,在显示时会增加一个密码的隐藏过程
在这里插入图片描述

这里就包含好几点可以进行处理,

  • 界面上不会显示明码防止窥屏
  • 界面上显示的黑色点数并不是真实的位数,防止通过位数来猜测
  • 使用系统级别安全的键盘或者自定义键盘输入
  • 禁止残障人员辅助功能
  • 隐私信息的后台模糊显示

逻辑设计安全

对于设计的业务逻辑应该是一个完整的闭环,对于攻击应该有意识的进行应对。
身为应用的门户,登录是所有人应对的第一关。不知道大家是否发现登录这个环节无论是在哪个应用中都算是比较奇葩的,有很多在登录时做的验证操作,短信验证人脸识别等等,这些操作的初衷是为了什么?

同样是提问:

  1. 登录是单点的么?
  2. 登录需要怎么识别是非机器操作?
  3. 登录需要超时么?
  4. 登录的出错尝试的多少次?
  5. 登录的出错验证需要什么进行处理?

一个完整的业务逻辑是需要考虑要考虑为了安全需要做到哪一步的?在用户使用的便宜性和安全级别之间做衡量。设计的东西太繁杂,需要在设计阶段就需要细细的琢磨,不能太过随意

这里吐槽一点,就是网易大师邮箱的登录,没法设置单点,也没放弃某一个客户端的登录,登录了多个邮箱后,旧的邮箱仍然在不断的推送。如果暂时把登陆过的设备出借他人了,没有任何办法知道我的信息到底分发到哪里去了,差评。

源码安全

项目管理级别

  1. 源文件下载的管理
    代码的下载管理,ssh下载优于账号密码的下载
    使用电脑的文件加密(usb口限制了)

  2. code Review
    代码安全的审核,防止溢出等导致可能的攻击
    依赖库的审核 (比如fastjson又双叒叕暴露了高危漏洞)
    sonar的静态检测工具是也是有必要的

  3. 秘钥管理
    秘钥是身份证,不要身份证人手一张,影响不好,最理想的状态是除了管理层应该谁也不知道签名的秘钥
    jekins gitlab 上面都可以支持参数配置,脚本运行打包的方式

源码自身的保护

  1. 文件混淆 资源混淆

  • 文件混淆和资源混淆的意义都在于降低其代码的可阅读性。增加反向阅读的难度。
    一般情况下资源是不用混淆的,出于做到更优的想法,资源的隐藏比没有隐藏肯定会更好。
    资源混淆是一个比较复杂的操作,目前看到是腾讯系的使用比较多。
    目前android使用的ProGuard的工具进行class文件的混淆操作,这里仍然提醒的一点是混淆是颗粒度,较多的开发者对于proGuard的工具没有清晰的认识,只会最简单的处理方式。对于安全级别高的应用,应该尽可能的做多的混淆
    处理前,
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3YT5E0cZ-1593566519776)(./images/1591150915047.png)]
    处理后
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rU40BZdK-1593566519779)(./images/1591150955297.png)]

  • 源码阅读工具
    阅读class的工具jd-gui下载地址
    github新出项目的比较好用的一键解读apk的神器 jadx附上对应的github地址
    如果前两者的转换有不全面的,借助baksmali 则可以直接转smali后进行阅读,smali类似于汇编语言的存在,如果到了这个级别,我就根本不在乎字节码的可读性了,因为本身就可读性很差了。
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0I49tWkn-1593566519780)(./images/1591151950836.png)]

  1. 静态保护 加花指令,防止静态分析工具,比如针对.so分析的IDAPro
    class的字节码世界已经不安全了,我要进行进一步的隐藏,内容下沉到.so中。
    (ps:我们公司的使用的易盾就是有这种操作)
    代码下沉后,仍然有比较好用工具比如IDApro这类静态分析工具能够进行阅读。
    这个时候我们可以加入适当的花指令
    花指令有两种表现方式:

    • 一种是无用的代码增加你的阅读量
    • 一种是陷阱指令使得的反编译工具在运行时出现问题或者不能正确的解析一些真实的代码
  2. 动态保护 加固,隐藏真实的内容
    加壳的程序可以有效阻止对程序的反汇编分析,以达到它不可告人的目的。这种技术也常用来保护软件版权,防止被软件破解
    在不同的平台上涉及到具体的操作手段会有所区别,但本质上都有壳程序优先获得应用的控制权,代替系统的加载过程,完成自定义的加载。在加载的过程中可以有加解密的操作,达到隐藏源码的作用。
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3AnSEXgy-1593566519781)(./images/1591325856024.png)]

运行时安全

  1. 简单的自证身份

  • 签名的合法性进行校验防止二次打包的应用


  • 篡改函数的返回值
    二次打包后可以任意的注入代码

  1. 数据传输安全
    你还在用http嘛?https一定是安全的嘛?
    一句话描述https: https的本质是通过非对称的加密方式保护对称秘钥的传输
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uaxYCXYm-1593566519783)(./images/1591154429328.png)]
    在实际的场景中由几种app使用Https的方式
    1、信任任何证书
    2、信任系统校验证书
    3、公钥校验
    4、证书全校验

  • 正确的使用https
    单端校验的完善(https中需要校验主机名等操作)
    最理想的是双端校验,服务器需要校验客户端的合法性,客户端也需要校验服务器的合法性
    同时也可以不信任代理,拒绝代理等方式来保护通信


  • 使用flidder主要针对是http/https的报文
    wireshark则主要是直接抓取的网卡的数据,更加的全面强大

  1. 数据落地安全

  • 日志不明码
    文件寻找合适的存储位置(android的存储位置为应用内部私有空间,应用外部私有空间,应用外部公共空间)
    文件落地加密
    数据库落地加密

  • root权限,获取所有的文件
    查看应用找到加密算法和秘钥
  1. 组件通信安全
    与SQL注入类似,Android中四大组件暴露的组件是很危险的Activity ContentProvider, Service, Broadcast

  • 获取不同的报文猜测应用的行为
    针对ContentProvider也可以进行注入
    • 隐藏不必要的组件
    • 组件的输入参数进行严格的校验
    • 所有涉及到跨进程传递的,只能是加密的敏感数据或者非敏感数据
  1. 反调试

  • 应用二次打包,调整清单文件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。
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JELnQCGS-1593566519784)(./images/1591324720463.png)]

    • 调试检测,根据自身的编译检测调试环境
      每个进程同时刻只能被1个调试进程ptrace,再次p自己会失败。所以可以主动ptrace自己,根据返回值判断自己是否被调试了
    • 进程名检测
    • 系统的调试检测函数
    • 断点搜索的检测(软断,硬断,内存断)
  • 检查虚拟机环境

    • 检查手机IMEI等一系列编号
    • 读取手机品牌信息
    • 检查mac地址
    • 处理器信息
  • 检查Xposed 框架

    • 遍历App安装列表检测
    • 通过自造异常检测堆栈信息,读取异常堆栈中是否包含Xposed字符串来识
    • 通过ClassLoader的 loadClass 加载列表检测
    • 由于Xposed的注入方式是通过底层SO文件修改被hook的方法为native来实现的,所以检测方也可以通过检测方法是否变成了native来达到检测的目的
    • 检测Xposed相关文件
    • 通过反射XposedHelper类和XposedBridge类做信息检测

结语

安全领域是一个庞大而专业的领域,身为非专业的人员很难到做精通,但是对其有所了解是非常有必要的事情。避免一些低级的错误,是我们作为一个合格的开发人员应该具备的素质。能够尽可能的了解安全的知识,才能做出一个靠谱的产品。
你没法赚到超出你认知范围外的钱,同样你也没法做出你认知范围外的防守。
共勉!

热门文章

暂无图片
编程学习 ·

Linux centos7 乱码设置中文字符集

1.locale 查看现在使用的字符集locale -a 查看有哪些字符集utf8的就可以显示中文yum -y install kde-l10n-Chinese 安装后选个uft8的 ,设置一下全局变量vi /etc/profileexport LANG=en_CA.utf8=号后面是字符集,这个大家随意最后让这个配置文件生效就可以了. /etc/profile 可能…
暂无图片
编程学习 ·

终于等到你,飞凌嵌入式i.MX6ULL核心板如约而至!

自从 2016年初,我们推出了FETMX6UL-C 核心板后,其高性价比、丰富的功能、15年生命周期、高稳定性的多方面优势,受到了广大客户的一致好评,在电力、医疗、工控、 物联网、能源管理、光伏、环境监测等领域取得大规模应用。 在此基础上, 我们推出了 FETMX6UL-C的“双胞胎兄弟…
暂无图片
编程学习 ·

操作系统——银行家算法

银行家算法安全性检测C++实现,求安全序列 #include <bits/stdc++.h>using namespace std; const int N = 100;const int total_resources = 3; //资源总数struct process {/* data */int resources_max[total_resources]; //每种资源的总大需求量int resources_a…
暂无图片
编程学习 ·

搭建一个完整的微服务系统(四):微服务的公共依赖

任何一个系统中,都有一个或多个基础项目,可生成jar包给所有服务依赖。在本示例(工程basejar)中,我给大家找了一些常用的进行说明,这些内容和业务无关,大家可以直接使用。 幂等相关这部分包括:AutoIdempotent.java、AutoIdempotentInterceptor.java、TokenService.java三个…
暂无图片
编程学习 ·

2020年上半年之总结

今天是2020年的上半年的最后一天即6月30号,这半年发生了许多的事情,又好像啥都没发生。身份的转变以及对未来的迷茫。从现在开始,好好工作,不要想着薪水多与少,做自己想做的事,珍惜生命,好好相待眼前人。
暂无图片
编程学习 ·

c++数制2~16数进制的转换

通项公式: while(n!=0){ a[i]=n%d; n=(n/d); i++; } 其中n为要转换的十进制的数。d为要转换的数制,如二进制为2. #include<iostream> using namespace std;int main() {int i,n,d,a[100];//n 为要转换的十进制数,d为要转为的数制 while(cin>>n>>d){i=0;wh…
暂无图片
编程学习 ·

利用BootStrap创建搜索框--」详解

今天学了bootstrap由于官网上没有搜索框,我要做一个网站正好需要,我就自己做了一个搜索框,话不多说直接上代码下面是jsp代码<div class="col-sm-5" id="so"><div class="input-group"><input type="text" class="…
暂无图片
编程学习 ·

Netty

Netty是什么?异步事件驱动的网络应用框架,可以快速开发一个可维护的高性能的服务端和客户端。都是谁在用Netty?Dubbo、zk、RocketMQ、es、Spring5(对于Http协议的实现)、Spak等大型开源项目使用Netty作为底层通讯的实现。Netty中的核心概念是什么?1、Channel管道,是对Sock…
暂无图片
编程学习 ·

Docker在阿里云上(Centos)下载安装

Docker作用 简单来说就是可以不在考虑项目的运行环境直接转移部署项目,只需要一个镜像文件,甚至可以理解为一个虚拟机(windows的VM软件里安装linux系统)。 卸载旧版本 sudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker…
暂无图片
编程学习 ·

跟汤老师学Java笔记: 流有哪三种分类方式

跟汤老师学Java笔记: 流有哪三种分类方式 完成:第一遍 1… 流有哪三种分类方式? 三类: 按流的方向(按内存为中心)分类: 输入流:用于读取数据,比如从文件中读取数据到程序中,由InputStream和Reader作为父类 输出流:用于写出数据,比如将程序中的数据写出到文件中,由…
暂无图片
编程学习 ·

小程序全局socket使用 并自定义发送心跳

//app.js App({globalData: {userInfo: nullsocketUrl:"wss:.....",//socketUrl//延迟timeout: 10000,socketHeartTimer: null,//socket连接回调函数callback: function () {},//socket连接定时器socketClientTimer: null,//当前socket是否连接isSocketConnect: fals…
暂无图片
编程学习 ·

詹姆斯高斯林的传奇人生

詹姆斯高斯林 (James Gosling)是一名软件专家。 高斯林1955年生于加拿大,从小就显露出不同寻常的智慧,12岁便能自己设计电子游戏。 1984年,高斯林进入太阳计算机系统公司,并在这家公司度过了26年时光。 1955年5月19日出生于加拿大,Java编程语言的共同创始人之一,一般公…
暂无图片
编程学习 ·

vulnhub靶机-djinn3

1、靶机ip:192.168.0.110(开机就提示:不是所有的都需要扫描发现主机)2、扫描靶机端口root@kali:~# nmap -A -p- 192.168.0.110 Starting Nmap 7.80 ( https://nmap.org ) Nmap scan report for 192.168.0.110 Host is up (0.0011s latency). Not shown: 65531 closed ports…
暂无图片
编程学习 ·

【漏洞通告】Treck TCP/IP协议库“ Ripple20”漏洞通告

【漏洞通告】Treck TCP/IP协议库“ Ripple20”漏洞通告 威胁对抗能力部 [绿盟科技安全情报](javascript:void(0)😉 昨天 通告编号:NS-2020-0039 2020-06-30TA****G: Treck、TCP/IP协议库、Ripple20漏洞危害: 攻击者利用此类漏洞,可造成拒绝服务、远程代码执行等。版本: 1…
暂无图片
编程学习 ·

React基本使用 - props与state、React事件

1、props 父组件传过来的参数 可以使用组件类的defaultProps属性,设置默认的props值 // Actor.js import React,{Component} from react; export default class Actor extends Component{render(){return (<div>hi, {this.props.name} - {this.props.works}</div>…
暂无图片
编程学习 ·

Java设计模式-5.适配器设计模式

在使用监听器的时候,需要定义一个类事件监听器接口,通常接口中有多个方法,而程序中不一定都用到,但又必须重写很繁琐,定义监听器时只要继承适配器,然后重写需要的方法。 适配器原理:适配器就是一个类,实现了监听器接口,所有抽象方法都重写了,但是方法都是空的,只重写…
暂无图片
编程学习 ·

07:从一个二维数组中查找一个数

题目:从一个二维数组中查找一个数 数组要求:从左到右,从上到小依次递增的矩形二维数组 思路:我们从矩阵的右上角开始查找,若该位置的数值小于目标值,列数减一;若数值大于目标值,行数加一,后续重复。 public class Offer07 {public static void main(String[] args) {i…
暂无图片
编程学习 ·

tensorflow-serving布置facenet心得

这个的东西困扰我很久,终于弄成了。不知道我做的是不是太繁琐,如果有人做的更简单,希望指出,谢谢。docker中,做了两个容器,一个放的mtcnn,一个放的facent。他们并不是多模型布置的。mtcnn其中包括:pnet,rnet和onet,这三个是多模型布置。客户端通过调用mtcnn,得到返回…