Android安全研究经验谈

安全研究做什么

从攻击角度举例,可以是:对某个模块进行漏洞挖掘的方法,对某个漏洞进行利用的技术,通过逆向工程破解程序、解密数据,对系统或应用进行感染、劫持等破坏安全性的攻击技术等。

而防御上则是:查杀恶意应用的方法,检测和防范漏洞利用,为增强系统和第三方应用的安全性提供解决方案等。

当然,通常情况下攻与防的概念是相对模糊的,一种安全技术往往在攻防两端都适用,也许更值得留意的是一种技术背后的思路和意识。研究员需要在新技术上倾注灵感,并且付出相当程度的汗水,才能换来某种成果——通过艰难的探索过程最终获得极大的成就感。我也经常在当Android adb shell中的$变成#时激动得大呼小叫(终端程序从一般用户提升到root用户),因为在此之前往往已经历了一个复杂的漏洞分析和利用过程。

需要具备的知识

在正式开始安全研究前,首先要掌握一定知识和技能。安全涉及的知识范畴是无限的,但大多数时候可以遇到问题再去了解相关的知识,不过以下内容是我认为应该提前掌握的。


【要掌握的理论知识】

主要是操作系统原理。这是非常重要的知识,是认识某一个具体系统的前提。虽然大学教材多以Linux内核为案例进行教学,但微软开源的Windows Reserch Kernel(简称WRK)同样也是非常棒的学习资料。比起单纯阅读源码和分析文章,自己动手编译系统内核,用调试器一步步调试内核更有帮助。最后还可以尝试自己编写内核驱动模块或分析已有的内核Rootkit来深入理解操作系统。我在大学里有很长一段时间在分析WRK,了解包括系统引导、内存管理、进程管理、线程调度、文件系统、网络驱动等内容,对我一直非常有帮助。鉴于嵌入式平台的开发和调试都有一定限制和不便,我不大建议一开始就在手机设备上研究操作系统内核,在PC上完成这部分知识储备会更方便。

就移动平台而言,理解操作系统有助于我们进一步理解Android系统本身,而在理解Android系统之后,才能开始讨论Android系统的安全问题,这是一个循序渐进的过程。

【几门需要掌握的语言】

研究员不需要特别强的软件开发能力,需要关注的是某种语言的内部实现过程。掌握C/C++,能理解该语言被编译器处理后汇编层面的实现原理。了解Java,需要理解Dalvik/ART虚拟机内部的实现过程。对于x86/ARM汇编,能读懂即可,遇到不认识的指令能从指令集手册中找到答案。

另外,还需要掌握一门脚本语言,主要用来快速编写小工具或者POC,我推荐Python,因为开源社区中大部分Android安全分析类工具都是用Python编写的,例如知名的Androguard和Drozer。

【逆向工程】

逆向工程绝对是一项必备技能。无论是分析恶意软件行为还是分析闭源软件漏洞,都需要逆向工程。但更重要的是,逆向工程能让我们从闭源程序中汲取营养,加快理解系统的速度。在对这类程序进行反汇编、调试的过程中,也会加深对操作系统、程序语言内部实现的理解,将上述知识串联起来。

神奇小子Geohot不久前利用CVE–2014–3153开发出了Android 4.4 Root通杀工具Towelroot,大多数人都不明白这个漏洞复杂的利用方法,但我通过对Towelroot逆向工程,第一时间理解了该漏洞利用的几项关键技术(Towelroot加入了大量混淆指令来反逆向工程,因而难度颇高)。也许我们不是天才,但逆向工程能让我们时不时地跟上天才的步伐。

理解Android系统

Android源码非常庞大,即便只看系统组件,恐怕也要好几年。更何况其源码并不是Android手机的全部,还有Linux内核、基带、bootloader、TrustZone等底层模块等待我们探索。我们只需了解支撑Android系统运转的核心服务,以及Android系统的安全机制设计即可,其余内容则可在需要用到时再去分析。

就组件来说,下面是应该优先理解的。

1. Zygote:Android应用的孵化器,一切Android程序由此进程fork而来。

2. Binder:Android的进程间通信机制,它是Android平台最核心的功能组件。

3. Package Manager Service:应用安装包管理服务,不仅负责包的安装和卸载,更重要的是负责Android应用信息的查询和控制,例如Android权限管理。

4. Activity Manager Service:管理Android框架层的进程,也包含了Android应用四大组件的逻辑实现。

5. Dalvik虚拟机:虽然即将被ART取代,但Dalvik依然是帮助我们理解虚拟机和Android可执行程序文件格式的好教材。

就安全机制来说,则需要了解下面几点。

1. 沙箱隔离:沙箱是基于不同应用之间User ID的不同而实现的,其本质是Linux对于不同用户间访问权限的隔离。

2. 应用权限控制:Android应用需要申请相应的权限才能访问系统的资源和信息,大多数权限由Android框架层的API进行控制,另一部分权限映射到应用所在的Group ID上,由Linux内核做出控制。

3. SE Linux:Linux内核层的安全增强,是一套独立于传统Linux权限访问控制的强制性权限控制机制。Google已将这套机制移植到Android内核,这给内核漏洞利用带来了一些挑战。


Android安全研究的热点方向与现状

【手机Root与内核漏洞挖掘利用】

在Android 2.x时代,往往利用一些用户层程序的漏洞即可将手机root,现在则主要依赖内核漏洞。Android为Linux内核引入了新的内核模块,以及不同厂商的驱动方案。这就为系统内核引入了新的安全隐患,无论是高通、MTK还是三星猎户座,或者华为海思的芯片,多少都出现过一些内核漏洞,这是Android平台内核的一个主要攻击点。随着Google将SE Linux引入Android,攻击面有所减小,但不能完全解决内核漏洞利用的问题。从防御角度来说,同样面临着挑战:一些APT攻击如果利用内核漏洞,将能拿到系统的完全控制权。Android平台内核漏洞长期以来一直都在持续曝光,漏洞利用与防范依然是持续的热点。

从这个方向入手,首先需要了解Linux内核,然后不断对目前已公开的CVE漏洞进行分析,理解漏洞的成因和各个类型。在漏洞利用方面,有开源项目run_root_shell可作为参考,该项目包含了多个经典漏洞的利用实现,是入门的好材料。除此之外,还可以关注国外的POC程序或对一键root类产品做分析。

【Android应用与系统框架层漏洞挖掘】

Android应用本身的问题主要集中在4大组件上,通常是一些逻辑处理问题导致信息泄露、身份认证绕过等。得益于Android沙箱机制,应用本身的攻击面是相对较小的,但一些开发人员似乎因此有恃无恐,在编码过程中表现出了较差的安全意识。此外围绕WebView或者SSL漏洞所引发的安全问题也比较常见。

框架层漏洞也是逻辑漏洞居多,但危害往往要比应用更大。比较著名的高危漏洞有Master Key签名绕过、WebView远程代码执行等。

目前已存在一些开源漏洞挖掘工具,如Drozer和Intent Fuzzer。我们可以在此基础上改进,如果有独特的挖掘思路,也可以自己尝试开发挖掘工具。

【恶意软件攻防】

从数量上看,隐私窃取和钓鱼软件是目前Android平台主要的恶意软件类型。

如果用户对于应用申请的权限毫不知情,一款应用便能轻松获取用户的短信、通讯录、地理位置、录音等私密信息。Android平台需要有主动防御程序控制应用获取隐私的行为,目前有两种方法实现,一种是集成到厂商的ROM代码中,另一种则是利用API Hook实现。无论使用哪种方式,目前面临的问题都是如何更智能地为用户管理权限,以减少防御软件频繁弹窗带来的打扰。

市面上还充斥着大量的仿冒支付类应用,他们看起来可能与正版应用没有区别,因为这些仿冒应用是由正版应用篡改而来的。这些软件通常会有用户名和密码窃取的恶意代码。安全软件需要通过签名、代码特征等方法对此进行识别。

从趋势上看,恶意软件也不再局限于Android安装包(APK)的形式进行分发,而往往会带有Linux可执行文件(ELF),对系统进行更深层次的攻击。 目前市面上的安全产品对APK文件的查杀已较成熟,但对系统原生层的恶意软件查杀还没有特别完善的实现,对一些APT级别的新型威胁防御也仍在探索阶段。

知名的恶意软件Oldboot就是恶意程序使用底层技术对抗查杀的典型案例,该程序的完整分析细节已被公开,读者可从网络上搜索文章参考,以更好地理解如何分析恶意软件行为。

【支付安全】

长期以来,手机支付使用短信验证码和独立支付密码解决支付者身份认证的问题。但仍存在短信遭人窃听或密码被窃取的风险,因此一些厂商效仿PC上的U盾方案,推出音频盾或蓝牙盾解决认证问题。而利用ARM架构下的TrustZone将支付认证过程独立于操作系统之外,也是一个方向。手机支付是很强的需求,依然有很多方案值得探索。

【应用加固(加壳)与逆向工程】

游戏、支付类应用都有很强的反逆向工程、防破解、防篡改的需求,目前已有几家比较成熟的方案出现。但目前对于Android ELF格式程序的保护还不够,终极防护当然是使用类似PC上的VMProtect虚拟机。逆向工程与加固保护是一个不断攻防的过程,加固方案需要不断提升自己的保护强度,修补方案上的漏洞。而对于逆向工程师来说,不能逆向不意味着不能分析程序行为。一个好的软件跟踪方法往往让你事半功倍。

目前国内比较知名的加固方案有梆梆加固、360加固保、爱加密等,大家可以在这些产品官网上看到相应信息。

【企业安全BYOD】

仅就终端设备本身来说,BYOD通常的方案是将手机系统隔离出两个环境:一个公用,一个私用,两者互不影响。三星的KNOX安全套件就提供了这样一个功能,使用Container,将需要隔离的公用应用包裹起来;Google也在开发类似应用,但传闻进展较慢。这类方案通常会和系统本身紧密结合,实现这样一套方案,或者发现这类方案中的安全漏洞,也是一个新的方向。

实例:Android 4.4.2系统vold漏洞

【如何在第一时间得知漏洞】

并非所有漏洞都会被纳入漏洞数据库(CVE),很多漏洞是被秘密修补的。一种方法是看版本升级时Android源码中的Change Log,运气好的话,你会从AOSP的Git Commit信息中注意到下面这句:

代码1


洞的信息。如果你对这条提交记录背后的问题足够敏感,就能发现问题。

事实上,注意到这条信息的人是少数。大多数人得知这个问题前,已有人掌握了技术细节并开发出了一款针对Moto的root工具放到了XDA论坛和Twitter上。

【如何掌握漏洞细节】

可能你会想到对这款名为“[Root 4.4.x] Pie for Motorola devices”工具进行逆向工程,但通过JEB,可以发现它经过了复杂的混淆。

这种混淆叫做dexGuard,比Google使用的ProGuard更复杂。花精力脱壳,还不如自己开发一个能做软件行为跟踪(trace)的ROM对其进行分析,但这是比较高级的话题。

先把工具放到一边,其实我们也可以通过现有的信息对该漏洞的利用方法进行分析。首先我们已获得了漏洞修补信息(其diff信息参见https://android.googlesource.com/platform/system/vold/+/0de7c61),这个问题出现在系统vold进程中,再结合源码和AIRBUS发布的分析报告,我们就可以得知以下信息。

1. 问题出现在系统进程vold(卷管理进程),这是一个以root权限运行的分区管理进程。具体出现问题的功能模块是ASEC(Android Secure External Caches),其大致功能是对应用在SD卡上存储的文件进行权限管理。因为SD卡的文件系统格式是FAT,它本身是不支持文件权限管理的。

2. 使用“vdc asec create YOURNAME ext4 none 2000 false”命令,vold进程接收到消息,在/data/app-sec目录下创建一个文件夹/data/app-sec/YOURNAME,并将这个目录mount成/mnt/asec/YOURNAME。

3. 如代码所示,vold在将/data/app-sec/和YOURNAME拼凑在一起时,使用了sprintf,未对YOURNAME这个字符串做任何校验。这意味着我们可以将YOURNAME构造成“../../PATH”的形式。这样vold将为我们mount任何目录,如果这个目录已存在(例如/sbin),将被新mount的目录覆盖。

代码2


【如何利用这个漏洞获取root】

既然vold可以为我们重复mount任意目录,就意味着我们可以使用自己指定的目录覆盖系统目录,也就等价于可以替换系统文件来获得以root身份执行的机会。将/sbin目录重新mount,替换/sbin/adbd文件,并且当系统进程adbd重新被init进程启动时,我们将有机会以root权限执行任意代码。这个漏洞利用代码非常简单。

代码3


这段命令首先创建了一个指向/sbin的符号链接/data/local/tmp/test1。然后使用vdc向vold发送触发漏洞的消息,vold将会把/data/app-sec/../../data/local/tmp/test1 mount起来。因为/data/local/tmp/test1是/sbin的符号链接,所以/sbin目录被覆盖成一个空分区。这个空分区是不可写入的,但我们能在该分区内建立符号链接,因此我为/data/local/tmp/adbd建立了一个符号链接是/sbin/adbd。这样一来,/sbin/adbd就指向了一个我们可控的文件:/data/local/tmp/adbd。当adbd进程被杀死,init进程将重新启动adbd,/data/local/tmp/adbd以root权限运行。后面要做的就是为手机安装su程序了,至此,手机root的过程完成。

转载于:https://www.cnblogs.com/LoongEmbedded/p/5298175.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/471180.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode 2182. 构造限制重复的字符串(贪心、map)

文章目录1. 题目2. 解题1. 题目 给你一个字符串 s 和一个整数 repeatLimit ,用 s 中的字符构造一个新字符串 repeatLimitedString ,使任何字母 连续 出现的次数都不超过 repeatLimit 次。你不必使用 s 中的全部字符。 返回 字典序最大的 repeatLimited…

Web框架——Flask系列之WTF表单验证练习(七)

一、Web表单 web表单是web应用程序的基本功能。 它是HTML页面中负责数据采集的部件。表单有三个部分组成:表单标签、表单域、表单按钮。表单允许用户输入数据,负责HTML页面数据采集,通过表单将用户输入的数据提交给服务器。 在Flask中&…

LeetCode 2185. 统计包含给定前缀的字符串

文章目录1. 题目2. 解题1. 题目 给你一个字符串数组 words 和一个字符串 pref 。 返回 words 中以 pref 作为 前缀 的字符串的数目。 字符串 s 的 前缀 就是 s 的任一前导连续字符串。 示例 1: 输入:words ["pay","attention",…

Web框架——Flask系列之Flask-SQLAlchemy安装与使用 定义数据模型(八)

Flask-SQLAlchemy安装及设置 SQLALchemy 实际上是对数据库的抽象,让开发者不用直接和 SQL 语句打交道,而是通过 Python 对象来操作数据库,在舍弃一些性能开销的同时,换来的是开发效率的较大提升SQLAlchemy是一个关系型数据库框架…

多线程篇-NSThread-简单使用

创建的三种方式 第一种 介绍/*alloc init 创建第一个参数:目标对象第二个参数:选择器,线程启动要调用哪个方法第三个参数:前面方法要接收的参数(最多只能接收一个参数,没有则传nil)*/ NSThread …

LeetCode 2186. 使两字符串互为字母异位词的最少步骤数

文章目录1. 题目2. 解题1. 题目 给你两个字符串 s 和 t 。在一步操作中,你可以给 s 或者 t 追加 任一字符 。 返回使 s 和 t 互为 字母异位词 所需的最少步骤数。 字母异位词 指字母相同但是顺序不同(或者相同)的字符串。 示例 1&#xf…

Web框架——Flask系列之Flask-SQLAlchemy数据库的基本操作(九)

数据库基本操作 在Flask-SQLAlchemy中,插入、修改、删除操作,均由数据库会话管理。 会话用 db.session 表示。在准备把数据写入数据库前,要先将数据添加到会话中然后调用db.session.commit()方法提交会话。 db.session.add(role&…

bash/shell编程学习(2)

先来复习上节重定向的用法&#xff1a; 1.快速清空文件 cat demo.txt < /dev/null注&#xff1a;linux中有一个经典名言【一切皆文件】&#xff0c;/dev/null可以认为是一个特殊的空文件&#xff0c;更形象点&#xff0c;可以理解为科幻片中的黑洞&#xff0c;任何信息重向定…

LeetCode 2187. 完成旅途的最少时间(二分查找)

文章目录1. 题目2. 解题1. 题目 给你一个数组 time &#xff0c;其中 time[i] 表示第 i 辆公交车完成 一趟旅途 所需要花费的时间。 每辆公交车可以 连续 完成多趟旅途&#xff0c;也就是说&#xff0c;一辆公交车当前旅途完成后&#xff0c;可以 立马开始 下一趟旅途。 每辆…

Web框架——Flask系列之综合案例——图书管理系统(十)

一、知识点: 表单创建数据库操作一对多关系演练 二、实现步骤: 创建数据库配置信息,定义模型类创建数据库表,添加测试数据编写html页面,展示数据添加数据删除书籍,删除作者 三、创建数据库连接信息,定义模型 from flask import Flask, render_template, redirect, url_for,…

LeetCode 2190. 数组中紧跟 key 之后出现最频繁的数字

文章目录1. 题目2. 解题1. 题目 给你一个下标从 0 开始的整数数组 nums &#xff0c;同时给你一个整数 key &#xff0c;它在 nums 出现过。 统计 在 nums 数组中紧跟着 key 后面出现的不同整数 target 的出现次数。换言之&#xff0c;target 的出现次数为满足以下条件的 i 的…

Web框架——Flask系列之request请求参数详解(十一)

一、request参数 request 就是flask中代表当前请求的 request 对象&#xff0c;其中一个请求上下文变量(理解成全局变量&#xff0c;在视图函数中直接使用可以取到当前本次请求) from flask import request 就是Flask中表示当前请求的request对象&#xff0c;request对象中保存…

LeetCode 2191. 将杂乱无章的数字排序(自定义排序)

文章目录1. 题目2. 解题1. 题目 给你一个下标从 0 开始的整数数组 mapping &#xff0c;它表示一个十进制数的映射规则&#xff0c;mapping[i] j 表示这个规则下将数位 i 映射为数位 j 。 一个整数 映射后的值 为将原数字每一个数位 i &#xff08;0 < i < 9&#xff…

LeetCode 2192. 有向无环图中一个节点的所有祖先(拓扑排序)

文章目录1. 题目2. 解题1. 题目 给你一个正整数 n &#xff0c;它表示一个 有向无环图 中节点的数目&#xff0c;节点编号为 0 到 n - 1 &#xff08;包括两者&#xff09;。 给你一个二维整数数组 edges &#xff0c;其中 edges[i] [fromi, toi] 表示图中一条从 fromi 到 t…

Web框架——Flask系列之Flask创建app对象 路由(十二)

一、初始化参数 import_name: 当前模块名 static_url_path:静态资源的url前缀&#xff0c;默认为‘static’ static_folder: 静态文件目录名&#xff0c;默认‘static’ template_folder: 模板文件目录名&#xff0c;默认‘templates’ 二、配置参数 app.config.from_pyfil…

bootstrap在iframe框架中实现由子页面在顶级页面打开模态框(modal)

我需要完成的效果&#xff1a; 1.在顶级页面打开模态框&#xff0c;并且遮罩层也要再顶级页面 2.单击遮罩层部分&#xff0c;模态框不关闭 问题描述&#xff1a; 不知为什么&#xff0c;可能是bootstrap前端框架添加遮罩层的一些问题。通过子页面在顶级页面打开模态框&#xff…

RIP协议及距离向量算法(详解)

一、路由选择协议分类回顾 二、RIP协议 RIP是一种分布式的基于距离向量的路由选择协议&#xff0c;是因特网的协议标准&#xff0c;最大优点是简单。 RIP协议要求网络中每一个路由器都维护从它自己到其他每一个目的网络的唯一最佳距离记录&#xff08;即一组距离&#xff09;。…

LeetCode 2194. Excel 表中某个范围内的单元格

文章目录1. 题目2. 解题1. 题目 Excel 表中的一个单元格 (r, c) 会以字符串 "<col><row>" 的形式进行表示&#xff0c;其中&#xff1a; <col> 即单元格的列号 c 。用英文字母表中的 字母 标识。 例如&#xff0c;第 1 列用 ‘A’ 表示&#xff…

OSPF协议及链路状态算法(详解)

一、路由选择协议分类回顾 二、OSPF协议 开放最短路径优先OSPF协议&#xff1a;“开放”标明OSPF协议不是受某一家厂商控制&#xff0c;而是公开发表的&#xff1b;“最短路径优先”是因为使用了Dijkstra提出的最短路径算法SPF。OSPF最主要的特征就是使用分布式的链路状态协议…

LeetCode 2196. 根据描述创建二叉树(哈希)

文章目录1. 题目2. 解题1. 题目 给你一个二维整数数组 descriptions &#xff0c;其中 descriptions[i] [parenti, childi, isLefti] 表示 parenti 是 childi 在 二叉树 中的 父节点&#xff0c;二叉树中各节点的值 互不相同 。此外&#xff1a; 如果 isLefti 1 &#xff0…