Android应用基本构造
1.了解APK文件
安卓应用的扩展名为.apk(Android Application Package),它是一个包含多个文件和文件夹的数据存档文件。
1.1 apk文件解压后的目录结构
- AndroidManifest.xml:包含应用的大部分配置信息、包名、应用组件、组件安全设置、应用所需权限等等。
- classes.dex:包含由开发人员编写的源代码生成的Dalvik字节码,以及应用在设备上运行时所执行的内容。
- resources.arsc:包含编译过的资源
- Res:包含应用所需的原始资源,如应用图标等图片。
- Assets:用于存放开发人员感兴趣的音乐、视频、预置的数据库文件,这些文件会与应用绑定。
- META-INF:用于存放应用签名和应用所用到的所有文件的SHA1摘要。
1.2 apk文件的存储位置
/data/app (用户安装的应用会存放在这个位置,/data/app我呢见夹中的apk文件是全局可读的。)

/system/app (系统镜像自带的应用会放在这个位置)

/data/app-pricate (设备上禁止复制的应用通常都存放在这个文件夹)

1.3 如何从设备上提取特定的应用
- 1.找到应用包名
- * 如果知道应用名称,可以使用下面的命令找到应用名称
- * > adb shell -d pm list packages | find "your app"
- 2.找到apk文件在设备上的存储路径
- * 使用下面的命令可以获取apk文件的路径
- * > adb -d shell pm path [包名]
- 从设备上拉取apk
- * 使用pull命令拉取应用
- * > abd -d pull /system/app/[file_apk]
1.4 Android应用的组件
1.4.1 Activity(活动)
定义
Activity是Android的四大组件之一。是用户操作的可视化界面;它为用户提供了一个完成操作指令的窗口。当我们创建完毕Activity之后,需要调用setContentView()方法来完成界面的显示;以此来为用户提供交互的入口。在Android App 中只要能看见的几乎都要依托于Activity,所以Activity是在开发中使用最频繁的一种组件。
- 一个Activity通常就是一个单独的屏幕(窗口)。
- Activity之间通过Intent进行通信。
- android应用中每一个Activity都必须要在AndroidManifest.xml配置文件中声明,否则系统将不识别也不执行该Activity。在android stdio会自动生成,但eclipse需要自己手动添加
- Activity的生命周期
在Android中会维持一个Activity Stack(Activity栈),当一个新的Activity创建时,它就会放到栈顶,这个Activity就处于运行状态。当再有一个新的Activity被创建后,会重新压人栈顶,而之前的Activity则会在这个新的Activity底下,就像枪梭压入子弹一样。而且之前的Activity就会进入后台。
一个Activity实质上有四种状态:
- * 运行中(Running/Active):这时Activity位于栈顶,是可见的,并且可以用户交互。
- * 暂停(Paused):当Activity失去焦点,不能跟用户交互了,但依然可见,就处于暂停状态。当一个新的非全屏的Activity或者一个透明的Activity放置在栈顶,Activity就处于暂停状态;这个时候Activity的各种数据还被保持着;只有在系统内存在极低的状态下,系统才会自动的去销毁Activity。
- * 停止(Stoped):当一个Activity被另一个Activity完全覆盖,或者点击HOME键退入了后台,这时候Activity处于停止状态。这里有些是跟暂停状态相似的:这个时候Activity的各种数据还被保持着;当系统的别的地方需要用到内容时,系统会自动的去销毁Activity。
- * 销毁(Detroyed):当我们点击返回键或者系统在内存不够用的情况下就会把Activity从栈里移除销毁,被系统回收,这时候,Activity处于销毁状态。
1.4.2 Service(服务)
定义
service(服务)是安卓中的四大组件之一,它通常用作在后台处理耗时的逻辑,与Activity一样,它存在自己的生命周期,也需要在AndroidManifest.xml配置相关信息。
服务(Service)是Android中实现程序后台运行的解决方案,它非常适合去执行那些不需要和用户交互而且还要求长期运行的任务。服务的运行不依赖于任何用户界面,即使程序被切换到后台,或者用户打开了另外一个应用程序,服务仍然能够保持正常运行。
不过需要注意的是,服务并不是运行在一个独立的进程当中的,而是依赖于创建服务时所在的应用程序进程。与某个应用程序进程被杀掉时,所有依赖于该进程的服务也会停止运行。另外.也不要被服务的后台概念所迷惑,实际上服务并不会自动开启线程,所有的代码都是默认运行在主线程当中的。也就是说,我们需要在服务的内部手动创建子线程,并在这里执行具体的任务,否则就有可能出现主线程被阻塞住的情况。
- service用于在后台完成用户指定的操作。service分为两种:
- * started(启动):当应用程序组件(如activity)调用startService()方法启动服务时,服务处于started状态。
- * bound(绑定):当应用程序组件调用bindService()方法绑定到服务时,服务处于bound状态。
- startService()与bindService()区别:
- * started service(启动服务)是由其他组件调用startService()方法启动的,这导致服务的onStartCommand()方法被调用。当服务是started状态时,其生命周期与启动它的组件无关,并且可以在后台无限期运行,即使启动服务的组件已经被销毁。因此,服务需要在完成任务后调用stopSelf()方法停止,或者由其他组件调用stopService()方法停止。
- * 使用bindService()方法启用服务,调用者与服务绑定在了一起,调用者一旦退出,服务也就终止,大有“不求同时生,必须同时死”的特点。
- * startService只是启动Service,启动它的组件(如Activity)和Service并没有关联,只有当Service调用stopSelf或者其他组件调用stopService服务才会终止。
- * bindService方法启动Service,其他组件可以通过回调获取Service的代理对象和Service交互,而这两方也进行了绑定,当启动方销毁时,Service也会自动进行unBind操作,当发现所有绑定都进行了unBind时才会销毁Service。
- 开发人员需要在应用程序配置文件中声明全部的service,使用<service></service>标签。
- Service通常位于后台运行,它一般不需要与用户交互,因此Service组件没有图形用户界面。Service组件需要继承Service基类。Service组件通常用于为其他组件提供后台服务或监控其他组件的运行状态。
1.4.3 Broadcast Receive(广播接收者)
定义
在Android中,广播是一种广泛运用的在应用程序之间传输信息的机制。而广播接收器是对发送出来的广播进行过滤接受并响应的一类组件。可以使用广播接收器来让应用对一个外部时间做出响应。例如,当电话呼入这个外部事件到来时,可以利用广播接收器进行处理。当下载一个程序成功完成时,仍然可以利用广播接收器进行处理。广播接收器不NotificationManager来通知用户这些事情发生了。广播接收器既可以在AndroidManifest.xml中注册,也可以在运行时的代码中使用Context.registerReceive()进行注册。只要是注册了,当事件来临时,即使程序没有启动,系统也在需要的时候启动程序。各种应用还可以通过使用Context.sendBroadcast()将它们自己的Intent广播给其他应用程序。
- 你的应用可以使用它对外部事件进行过滤,只对感兴趣的外部事件(如当电话呼入时,或者数据网络可用时)进行接收并做出响应。广播接收器没有用户界面。然而,它们可以启动一个activity或serice来响应它们收到的信息,或者用NotificationManager来通知用户。通知可以用很多种方式来吸引用户的注意力,例如闪动背灯、震动、播放声音等。一般来说是在状态栏上放一个持久的图标,用户可以打开它并获取消息。
- 广播接收者的注册有两种方法,分别是程序动态注册(在运行时的代码中使用Context.registerReceive()进行注册)和AndroidManifest文件中进行静态注册。
- 动态注册广播接收器特点是当用来注册的Activity关掉后,广播也就失效了。静态注册无需担忧广播接收器是否被关闭,只要设备是开启状态,广播接收器也是打开着的。也就是说哪怕app本身未启动,该app订阅的广播在触发时也会对它起作用。
1.4.4 Content Provider(内容提供者)
- android平台提供了Content Provider使一个应用程序的指定数据集提供给其他应用程序。其他应用可以通过ContentResolver类从该内容提供者中获取或存入数据。
- 只有需要在多个应用程序间共享数据是才需要内容提供者。例如,通讯录数据被多个应用程序使用,且必须存储在一个内容提供者中。它的好处是统一数据访问方式。
- ContentProvider实现数据共享。ContentProvider用于保存和获取数据,并使其对所有应用程序可见。这是不同应用程序间共享数据的唯一方式,因为android没有提供所有应用共同访问的公共存储区。
- 开发人员不会直接使用ContentProvider类的对象,大多数是通过ContentResolver对象实现对ContentProvider的操作。
- ContentProvider使用URI来唯一标识其数据集,这里的URI以content://作为前缀,表示该数据由ContentProvider来管理。
- 内容提供程序以一个或多个表格的形式为外部应用提供数据。如果应用需要与其他应用共享数据,内容提供程序就是一种方法,它可以充当应用间的数据共享接口。内容提供城西使用标准的insert()、query()、updata()、delete()等方法来获取应用数据。所有的内容提供程序都使用content://开头的特殊格式的URL。只要知道这个URL并拥有合法的权限,任何音乐都可以从内容提供程序的数据库中进行数据插入、更新、删除、和查询等操作。
- * 例如,通过使用content://sms/inbox内容提供程序,任何应用都可以从内置短信应用的数据仓库中读取短信,前提是应用需在AndroidManifest.xml文件中声明*READ_SMS权限。
1.5 Android应用的构建过程
参考链接:http://developer.android.com/adk/installing/studio-build.html

从命令行编译DEX文件过程:
javac [java文件]
- 然后使用java执行.class文件的类,在控制台输出“hello word”
java Helloword

- 但是该class文件还无法在安卓应用执行,因为安卓系统拥有自己的字节码格式,Dalvik,所以需要将class文件转化为dex文件
dx --dex --output=[file.dex] [class_path]
#dx.bat 文件在Android SDK中

adb push hacking.dex /data/local/tmp
adb shell
dalvikvm -cp [path to dex file] [类名]

1.6 应用运行时发生了什么
- 安卓系统启动后,Zygote进程也会随之启动,它会监听新应用的启动请求,当用户点击一个应用时,会通过Zygote启动该应用,Zygote收到启动新应用的请求后,会使用fork系统调用来创建一个自身的副本,这种启动方式效率更高,速度更快。新启动的应用进程会加载运行应用所需的多有代码。class.dex文件包含能够兼容Dalvik虚拟机的所有字节码,在使用安卓5.0版本及以上版本时,默认的运行环境是ART,在这个新环境中。dex2oat工具会把class.dex文件转换成OAT文件。
- ART-新订单安卓运行环境
- * Dalvik在应用运行时,将字节码转换为原生机器码,这是即时编译
- * ART可以将应用的字节码转换为原声机器码,这是提前编译。优点是无需每次启动应用都转换字节码,虽然第一次启动会稍有延迟,但是下一次应用性能就会得到大幅度的提升。
1.7 理解应用沙盒
一个应用对应一个UID
- 安卓是基于Linux内核,用户分离模式同样适用于安卓,但又和传统的Linux不同。每一个安装在设备上的应用都有属于自己的UID,这使得每个应用及其资源都被沙盒化,任何其他的应用都不能访问。
- 用户u0_a28对应的UID是10028,这些用户名分别对应了一个从10000开始的UID
- 每一个应用在/data/app文件夹中都有各自存储数据的入口,每个应用的目录都归它自己所有,其他应用不能读写这些目录。
2.安卓应用简介
2.1web应用
web应用是通过使用javaScript、HTML5等web技术来实现交互、导航以及个性化功能的。web应用可以在移动端设备的web浏览器中运行,并通过向后台服务器请求web页面来进行渲染。一个web应用可以有浏览器渲染的版本,也可以有作为独立应用的版本。
2.2原生应用
不同于web应用,原生应用具有优良的性能和高度的可靠性,-,而且还能利用安卓系统提供的高速本地支持,所有原生应用的响应速度很快,另外,用户不连接网络也可以使用,但是使用原生技术开发的应用不能够跨平台,只能使用某一特定平台开发。
2.3混合应用
混合应用尝试综合利用原生应用和web应用的优点,使用web技术编写,像原生应用一样在设备上运行,混合应用在原生容器中运行,利用设备的浏览器引擎(不是浏览器)在本地渲染HTML,并处理javaScript。混合应用能够通过一个从web应用访问到这些接口,混合应用也通常使用PhoneGap、React Native等框架进行开发。
3.移动应用威胁建模
3.1移动应用架构
社交类、银行类等移动应用具有很多需要使用网络通信的功能,所以如今大部分移动应用都采用常见的客户端-服务端架构,想要了解这类应用,需要充分考虑应用的各个方面,包括客户端、后端API、服务器漏洞以及数据库等,这些地方的任何一个入口都有可能对整个应用或应用数据造成威胁。一个安卓应用通过后端API连接服务器,服务器又和数据库相连接。
在开发软件时,很多企业都采用安全软件开发生命周期(SDLC),从而保证软件开发生命后期中的每一个阶段的安全性。
3.2微软公司安全开发流程
3.2.1 威胁建模
通过界定资源,所提供的数值以及可能攻击资源的威胁者来识别应用的威胁,最好在应用设计阶段构建威胁模型。
3.2.2 静态分析
在实现阶段,建议在每个发行周期对源代码至少进行一次静态分析。这样能让利益相关者了解风险的基本情况,便于他们决定是接受这些风险,还是让开发团队在应用正式发布前修复这些问题。
3.2.3 动态分析
动态分析是在安全软件开发生命周期的测试阶段完成的。动态分析是一种在应用运行过程中查找问题的技术。能帮助企业在发布应用前了解应用的安全情况。
3.3 客户端存在的威胁
3.3.1 静态应用数据
随着移动应用的出现,在客户端存储数据的概念被广泛采用。很多移动应用在设备上存储未经加密的敏感数据,这是移动应用存在的主要问题之一。这些数据可能是敏感的、机密的或者私人的。有多种方法可以利用设备上的数据,拥有设备物理访问权限的攻击者几乎可以轻面易举地窃取这些数据。如果设备已经ROOT过了或者越狱了,那么恶意应用就可能窃取这些数据。所以,我们必须要确保应用不在设备上存储用户名、密码、认证标记、信用卡号码等敏感数据。如果不得不存储这些数据,就必须将其加密,谨防被攻击者窃取。
3.3.2 传输中的应用数据
需要与后台进行通信的移动应用极易受到攻击,攻击者想要窃取传输中的数据。终端用户经常连接咖唯店和机场的公用网络,而此时攻击者就可能使用burp代理、MITM代理、 SSL MitM代理等工具窃取数据。随着智能手机应用的使用,进行这类攻击已经变得非常容易,因为无论去哪里,我们都会隨身携带手机。
3.3.3 代码漏洞
不具有安全措施的移动应用在遭受各种攻击时会变得脆弱不堪。应用中的编码错误会导致严重的漏洞,进而影响用户数据和应用数据安全。这些失误的例子包括导出的内容提供程序、导出的activity,客户端注人,等等。攻击场景包括拥有设备物理访问权限的攻击者可能窃取另一个用户的会话,设备中的恶意应用可以读取其他应用中由于编码错误而暴露的数据,能访问应用二进制数据的攻击者可能会对应用进行反编译从而查看源代码中硬编码的证书。
3.3.4 应用数据泄露
几乎所有平台的移动应用都存在这一个问题。应用可能会无意间将敏感数据泄漏给攻击者,开发者需要格外注意这一点。开发人员需要移除在开发阶段中用于打印日志的代码,还必须保证没有容易泄漏的数据。这是因为应用沙盒不适用于这一类型中的某些攻击。譬如、用户从应用中复制了像安全问题答案之类的敏感数据,这些数据就会被存放在设备的剪贴板上,而剪贴板并不在沙盒中。设备上的其他应用不需要知道之前的应用,就可以读取这些数据
3.3.5 平台问题
为移动应用设计威胁模型时,考虑针对该应用运行平台的威胁很重要。以安卓平台为例,面向安卓平台开发的原生应用很容易被反编译,而且很容易查看Java源代码这样,攻击者就能查看应用的源代码以及代码中被硬编码的敏感数据。此外,攻击者还能修改应用代码,然后重新编译,并把应用发布到第三方应用市场上。如果应用是敏感应用或者付费应用,那么就必须对应用进行完整性检查。虽然上述问题对IOS这样的系统影响相对较小,但如果设备越狱了,那么也会存在系统方面的问题。
3.4 后端存在的威胁
3.4.1 身份验证授权
在后端API开发中,开发人员经常创建自定义身份验证。在身份验证与授权中可能存在相关的漏洞。
3.4.2 会话管理
移动平台通常使用身份验证令牌来管理会话。用户首次登陆后,会得到一个身份验证令牌,这个令牌在接下来的会话中都会用到。如果身份验证令牌在销毁之前没有得到妥善的保护,这就有可能导致一次攻击。只在客户端结束会话,二服务器没有结束会话,这是移动端常见的问题。
3.4.3 输入验证
输入验证是应用中已知的常见问题。如果不进行输入验证,可能会存在sql注入、命令注入以及跨站脚本攻击等风险。
3.4.4 错误处理不当
应用错误对攻击者很有吸引力,如果错误处理不当,而API针对特定的请求抛出数据库异常或服务器异常,那么攻击者就可能利用这些错误进行巧妙的攻击。
3.4.5 脆弱的加密方法
加密是开发者在开发过程中另一个经常犯的错误,虽然各个平台都支持通过加密的方法来保证数据安全,但秘钥管理是客户端存在的主要问题,同样,也需要安全地存储后台数据。
3.4.6 数据库攻击
攻击者有可能在未授权的情况下直接访问数据库。例如如果没有强认证保护,攻击者有可能在未经授权的情况下访问phpmyadmin等工具数据库控制台,另一个例子就是访问未授权的MongoDB控制台,因为MongoDB默认不需要任何认证就能访问它的控制台。
4.OWASP移动应用十大风险
4.1 弱服务器端控制
弱服务器端控制是指省队应用后台的攻击。目前,大多数应用都要使用网络连接,并通过REST或者SOAP API接口来链接后台服务器。移动应用的安全原则和传统web服务器以及web应用的安全原则相同,因为我们只是使用了不同的前端(移动客户端),而后端还是相同的。常见的攻击向量包括找出暴露的API入口,查找各种漏洞,利用配置错误的服务器等。
4.2 不安全的数据存储
开发者会假定攻击者无法访问存储在设备上的数据,基于这一假设,开发者通常会共享首选项或者SQLite数据库将敏感数据存放在设备的文件系统中,比如用户名、身份验证令牌、密码、PIN码等个人信息。有多种方法可以访问存储在设备上的数据,常见的技术包括ROOT设备,然后访问这些数据,或者使用基于备份文件的攻击等。
4.3 传输层保护不足
对移动应用进行渗透测试时,通常会通过网络传递证书和会话令牌。所有我们可以通过分析流量来检查应用是否通过网络传输了敏感数据,这是一个不错的方法。还有一个重要的情况是,应用大部分模块都是易受攻击的。如果需要通过HTTPS进行认证,并通过HTTP发送认证cookies,那么这个应用就容易受到攻击,因为攻击者很容易获取通过HTTP传递的cookies,而这些cookies与用户名和密码一样强大,都可以登录应用。缺乏证书验证和弱握手协议也是传输层安全协议中常见的问题。
4.4 意外的数据泄露
如果应用把用户或者其他地方的敏感信息当作输入,就可能导致这些数据被存储到设备中一个不安全的位置。设备中的其他恶意应用就有可能访问这个不安全的位置,最终使设备处于高风险之中。在严重的攻击下,代码将变的脆弱不堪,因为利用这些侧信道数据泄露的漏洞非常容易。攻击者只需要编写一段简短的代码,然后就能访问敏感信息。我们甚至可以使用adb等工具就能访问这些存储位置。
可能导致数据泄露的几种情形
- 内容提供程序泄露
- 复制粘贴缓存
- 调试日志
- URL缓存
- 浏览器cookies
- 发送给第三方的分析数据
4.5 糟糕的授权和身份认证
移动应用和设备的易用性指标与传统的web应用和笔记本电脑不同。考虑到移动设备的输入形式,它的PIN码和密码通常比较短。基于实用性的考量,移动应用的认证和传统的web认证方案也不同。如果没有采取相应的措施,攻击者很容易就能暴力破解应用汇总这些简短的PIN码,我们可以向服务器发生恶意请求,并观察这些请求是否得到响应来尝试访问应用更高权限的功能,这样就可以测试糟糕的授权方案。
4.6 被破解的加密技术
如果开发者在应用中使用加密技术,就会涉及加密技术破解的问题,有多种原因导致安卓应用的加密技术能够被破解
- 使用较弱的算法来进行加密解密,包括使用有重大漏洞的算法或者不满足现代安全要求,比如DES,3DES等
- 使用强加密算法,但实现方式不安全:包括在本地数据库中存储秘钥,将秘钥硬编码到代码中。
4.7 客户端注入
客户端注入的结果是,可以通过应用在移动设备上执行恶意代码。通常,恶意代码通过不同的方式借助威胁代理输入到移动应用中。
- webview注入
- 通过原始sql语句对SQLite数据库进行传统的sql注入
- 内容提供程序sql注入
- 内容提供程序路径遍历
4.8 通过不受信任的输入进行安全决策
开发者应该假设未授权的用户可以通过不正确的输入过度使用应用的敏感功能,特别是安卓平台,攻击者可以拦截调用(进程间通信或web服务调用),并篡改其中的敏感参数。不能实现这类功能就会导致应用产生错误,甚至让攻击者获得更高的权限。使用不正确的Intent调用敏感的activity就是例子。
4.9 会话处理不当
移动应用使用诸如SOAP或REST一类的协议来链接服务器。他们都是无状态协议,当移动客户端应用使用这些协议时,客户端在身份验证完成后会从服务器获得一个令牌。用户在会话期间将使用这个令牌。OWASP的会话处理不当就是指攻击和保护这些会话。这个令牌在客户端失效后,却没有服务器上失效,这是移动应用的一个常见问题。通常,应用受到这个令牌会通过共享首选项或SQLite数据库存在客户端的文件系统中。一旦恶意用户获得了这个令牌,而服务器没有及时让这个令牌失效,那他就可以随时使用这个令牌。其他可能出现的情况包括会话超时、令牌创建以及过期令牌等。
4.10 缺乏二进制文件保护
逆向工程是大部分安卓应用最常见的问题之一。攻击者得到应用的二进制文件后,首先会反编译或者拆解这个应用。攻击者通过这种方式可以查看到硬编码的秘钥,查找漏洞,甚至通过重新打包拆解后的应用来修改应用功能。虽然混淆代码并不难,但是大部分的应用并没有这么做。如果没有对源代码进行混淆,攻击者只需使用一个合适的工具就能完成这些工作。比如apktool或者dex2jar。虽然有些应用会检测设备的root状态,但是通过对应用进行逆向工程或者hook应用流程就能绕开这些检测。
5.数据存储与数据安全
5.1 什么是数据存储
安卓使用了类似Unix中的文件系统来进行本地数据存储,用到的文件系统有十几种,如FTA32、EXT等。事实上,安卓系统中的一切都是文件。因此,我们可以使用下面的命令从/proc/filesystems文件中查看文件系统详情:
adb shell cat /proc/filesystems
安卓在filesystems这个文件中存储了许多详细的信息,比如内置应用等。任何拥有物理访问权限的人都能轻易从中获取许多敏感信息,如照片、密码、GPS定位、浏览历史或者公司数据等。应用开发人员应确保数据存储的安全,如果没有做到这一点,将会对用户数据产生不利影响,甚至导致严重攻击。
- /data 存储应用数据。/data/data目录用于存储与应用相关的私人数据,如共享首选项、缓存、第三方库等。通常,应用在安装完成后会存储如下信息(只有特定用户才能访问这个目录,其他应用则不能。)
- /proc:存储与进程、文件系统、设备等相关的数据。
- /sdcard:SD卡用于增加存储容量。/sdcard通常对应内置SD卡,/extsdcard则对应外置SD卡。
5.2 Android本地数据存储技术
5.2.1 共享首选项
- 共享首选项是一些XML文件,他们以键值对的形式存储应用的非敏感设置信息。所存储的数据类型通常是boolean、float、int、long、string等。
- 查看应用是否创建了共享首选项文件
/data/data/<包名>/shared_prefs/<filename.xml> ![image]
- 使用cat 查看xml文件,如果不习惯使用shell,可以使用下面的命令将文件下载到操作系统,使用文本编辑器打开
adb pull [文件路径] [存放文件的路径]

5.2.2 SQLite数据库
SQLite数据库是基于文件的轻量级数据库,通常用于移动环境。安卓系统同样支持SQLite框架,因此你经常会发现许多实用SQLite数据库存储的数据应用。由于安卓系统在安全性方面的限制,应用存储在SQLite数据库中的数据默认不能被其他应用访问。
SQLite数据库是基于文件的轻量级数据库,扩展名通常为.db或.sqlite。安卓系统完全支持SQLite数据库。应用中的其他类都能访问应用创建的数据库,但是其他应用则不能访问。
安卓应用存放数据库文件的位置:/data/data/<包名>/databases/<数据库名.db>

使用pull命令将db文件下载到电脑,使用SQLite浏览器,将db文件拖放到SQLite窗口,双击浏览数据

5.2.3 内部存储
- 内部存储也被成为设备的内部存储,可以将文件存储到内部存储空间。由于能被直接访问,因此它能快速响应内存访问请求,与应用相关的全部数据几乎都在这里被使用。从逻辑上来说它是手机的硬盘。在安装过程中,每个应用都在/data/data/<应用包名>/下创建了各自的文件目录,这些目录对每个应用都是私有的,其他应用没有防问权限。当用户卸载后,这些目录中的文件将会被删除。
- 有些应用会使用内部存储保存应用私钥,通过阅读代码可知,私钥的存放位置,例如(files目录下的private.key),同样可以使用pull下载到本地查看
5.2.4 外部存储
- 外部存储是安卓系统中一种用于存储文件的全局可读写的存储机制。任何应用都能访问外部存储区域并读写文件,由于这一特性,敏感文件不应该存储在这里。开发人员需要在AndroidManifest.xml中声明合适的权限才能进行这些操作。
- 将数据存储在SD卡时特别需要注意,因为它是全局可读取的,用户甚至可以轻松将SD卡从
- 应用要访问外部存储,前面的代码需要在AndroidManifest.xml文件中声明WRITE_EXTERNAL_STORAGE权限:<uses-permissionan
5.2.5 用户字典缓存
- 用户字典是大多数移动设备所具有的一个非常方便的功能,能够让键盘记住用户经常输入的词组。当我们使用键盘输入特定的词组时,它能自动提供一些补全建议。安卓系统同样具有这一功能,它将常用词组存放在一个名为user_dict.db的文件中。因此,应用开发人员应小心,如果允许缓存输入安卓应用的敏感数据,那么任何人都可以通过浏览user_dict.db文件或使用其内容提供程序的URL访问这些数据。
- 由于任何应用都可以通过用户字典的内容提供程序访问其内容,因此攻击者可以轻松读取和搜集其中的有用信息。与前面处理Android Backup Extractor.db文件的方式一样,我们将user_dict.db数据库文件拉取到计算机,并使用SQLite打开
- > adb pull /data/data/com.android.providers.userdictionary/databases/user_dict.db

5.2.6 不安全的数据存储-NoSQL数据库
- 目前,NoSQL数据库使用广泛,企业普遍使用了诸如MongoDB、CouchDB等NoSQL数据库,这些数据库同样适用于移动应用。与其他本地存储技术类似,如果NoSQL数据库通过不安全的方式存储数据,就可能会被利用。
- 使用下面的命令安装:adb install nosqldemo.apk
- 在本例中,应用安装在/data/data/com.example.nosqldemo中,使用ls查看发现,这里只有files目录,没有databases文件夹,实际上,确实数据库目录是因为Couchbase使用files目录存储数据库文件,
- 进入files目录,查看其中的文件,Couchbase将数据存储在扩展名为.cblite的文件中,同样可以拉取到本地,查看文件,由于它是文本文件,而且是以JSON格式存储数据。可以查看到存储的信息。
5.2.7 备份技术
前面所有的例子都是基于已ROOT的设备。现在探讨使用备份功能在未ROOT的设备上查看应用的内部存储。利用特定能够应用或设备的备份文件,可以检查其安全问题。
1. 使用adb backup命令备份应用的数据
下图展示了adb backup命令提供的选项

我们可以使用下面的命令备份整部安卓手机:adb backup -all -shared -apk
也可以使用下面的命令备份某一个应用:adb backup -f <文件名> <包名>
运行命令后,屏幕提示点击Back up my data按钮,还为我们准备了加密备份的选项,只需输入密码即可。点击备份按钮后,它会在工作目录下创建一个名为backup.ab的文件
2.使用Android Backup Extractor将.ab格式转换为.tar格式
- 即使我们得到了backup.ab的文件,我们还是不能直接读取文件内容,首先需要转换为我们能理解的格式,这里用到Android Backup Extractor,它能将.ab文件转换为.tar文件
- 下载Android Backup Extractor:http://sourceforge.net/projects/adbextractor/
- 解压下载好的文件,将abe.jar文件复制到backup目录下,同时还有backup.ab文件
- 使用下面的命令来查看这个工具提供的选项:java -jar abe.jar --help
java -jar abe.jar -debug unpack backup.ab backup.tar
3. 使用pax或star工具解压TAR文件
tar和7-ZIp等标准的解压工具不能解压abe.jar生成的文件,因为他们要求保存的目录时结尾要有斜线。
- 现在我们需要使用Android Backup Extractor中的star工具或Cygwin中的pax工具
- star.exe的语法如下:star.exe -x backup.tar
4. 分析上一步解压后的内容,查找存在的安全问题
解压得到名为com.xxx.xxxx的文件夹,它包含了如下文件夹
- _manifest:应用的AndroidManifest.xml文件
- db:包含应用所使用的.db文件
- f:保存各种文件
- sp:保存共享首选项的XML文件
- r:保存视图、日志等文件。
5.同样可以修改导出的备份文件,然后将其还原至设备
- 备份目标应用:adb backup -f <文件名> <包名>
- 使用dd命令删除文件头,然后保存修改后的文件,保存文件列表,并记录文件顺序
dd if=backup.ab bs=24 skip=1 | openssl zlib -d > backup.tar
tar -tf backup.tar > backup.lsit
- 解压TAR文件,然后根据需要修改应用内容,比如修改PIN码和应用设置等。
tar -xf backup.tar
- 根据修改后的文件重新创建.tar文件
star -c -v -f newbackup.tar -no-dirslash list=backup.list
- 将原始的.ab文件的文件头添加到新文件上
dd if=mybackup.ab bs=24 count=1 of=newbackup.ab
- 将修改后的内容添加到文件头
openssl zlib -in newbackup.tar >>newbackup.ab
- 还原修改过的备份文件
adb restore newbackup.ab
5.2.8 其他存储方式
除了外部存储方式,其他存储方式都将数据存放在/data/data目录下的文件夹中,其中包含缓存、数据库、文件以及共享首选项这四个文件夹。每个文件夹分别用于存储与应用相关的特定类型的数据。
- shared_prefs:使用XML格式存储应用的偏好设置;
- lib:存储应用需要的或导入的库文件;
- files:用于存储与应用相关的文件;
- cache:用于存放缓存文件;
5.3 怎么确保数据安全
- 很明显,敏感信息不应该明文存储,尽量不要将敏感信息存储到设备上,而是应该放到服务器上,如果必须选择前者,在存储数据时使用加密算法
- 使用类似AES等堆成加密算法时,秘钥管理是一个问题,可以使用密码加密(PBE)的方式,秘钥就会基于用户输入的密码生成。如果考试使用散列来加密,那就选择一个强的散列算法并对其加盐。
感兴趣的师傅可以关注公众号,感谢支持。
