移动APP安全测试总结

1.移动 APP安全风险分析
1.1安全威胁分析
安全威胁从三个不同环节进行划分,主要分为客户端威胁、数据传输端威胁和服务端的威胁。

1.2面临的主要风险

1.3Android 测试思维导图

1.4反编译工具

有两种反编译方式,dex2jar 和 apktool ,两个工具反编译的效果是不一样的,dex2jar反编译出java 源代码, apktool反编译出来的是java 汇编代码。
dex2jar 主要是用来把之前zip 解压出来的classed.dex 转成 jar包的,jd-gui 主要是用来打开Jar 包的

2本地客户端安全

2.1反编译保护

2.1.1问题描述

APP 源代码对于一个公司是非常重要的信息资源,对APP的保护也尤为重要,APP的反编译会造成源代码被恶意者读取,以及APP 的逻辑设计,
反编译方法
我们一般想要反编译一个apk,无非就是想获得三样东西:图片资源、XML 资源、代码资源一. 图片资源获取
首先准备一个apk,这里是一个.apk 后缀的文件,我们先把后缀改成,zip,打开zip 文件在 res 目录下,我们就可以获取到我们需要的图片了。
XML 资源获取
我们可以在刚刚打开的zip 文件目录下看到很多.xml 的文件,这个xml 文件是无法直接打开的,当你尝试着打开的时候都是乱码或者是空白,那么我们要如何获取到这个xml资源呢,这时候就需要借助一个jar包,就是axmlprinter2.jar ,这个东西你只要百度下,就能搜到。然后你把他放跟你解压出来的xml 放在同级目录下,用cmd命令找到这个目录,
我这边的示例是将xml 放在了 E盘,大家根据情况,cd 到自己解压出来的目录下,然后执行
Java -jar AXMLPrinter2.jar xxxxx.xml>xxxxx.txt,这个时候你就能获取到xml 里的东西啦
代码资源获取
这个重中之重了,这也是我们主要想要获取到的东西。但是存在一点,这里能够正确反编译出来的只有未加密或者没有混淆的代码,如果想要反编译一些加密或者混淆后代码,俺们就需要其他途径解决了

首先要准备两样东西:dex2jar.rar 和 jd-gui.zip 这两个工具。
dex2jar主要是用来把之前zip 解压出来的classed.dex 转成 jar 包的
jd-gui 主要是用来打开Jar 包的
dex2jar 用法:
把 dex2jar解压后,然后将之前zip 的 classes.dex 放到dex2jar 目录下, 注意,必须要跟dex2jar.bat 是同级目录。
然后又要用到cmd,cd 到 dex2jar 目录下,打命令行
dex2jar.batclasses.dex
然后你的目录里会多一个jar 包多一个classes-dex2jar.jar 的文件
然后在用 jd-gui 把 jar 包打开,最终 apk 的代码就这样被剥离出来了
2.1.2、检测方法
通过反编译工具看是否能够对 APP进行反编译

2.1.3、修复方法
采用加密和混淆技术达到反编译保护。
混淆技术作用是增加了用户反编译后阅读代码的难度。

2.2APP二次打包

4.1.1二次打包描述
“ AndroidAPP二次打包 ”则是盗版正规Android APP,破解后植入恶意代码重新打包。不管从性能、用户体验、外观它都跟正规APP 一模一样但是背后它确悄悄运行着可怕的程序,它会在不知不觉中浪费手机电量、流量,恶意扣费、偷窥隐私等等行为。面对二次打包不少公司都有自己的防范措施,知名公司的APP 几乎都是自己在程序内部做过处理防止其APP 被二次打包,一旦打包后重新运行则程序自动退出。接下来,我就来详解一下如何防止APP被二次打包。要实现代码内部防止APP 被二次打包首先得了解APK 的机器识别原理,APK 的唯一识别是依靠包名和签名来做鉴定的,类似豌豆夹的洗白白、360 手机卫士等安全软件对APK的山寨识别,他们就是依赖包名来确定APK 然后通过签名来确定其是否山寨。所以说自己的程序内部在启动的时候可以通过获取APK本身的签名然后和正确的签名做对比来识别自己是否被二次打包。
4.1.2防二次打包检测方法
利用二次打包工具对APP进行二次打包,看 APP 能否成功打包运行,如果重新打包后无法运行程序说明有防二次打包安全措施。
4.1.3防二次打包修复方法
采用签名的方法进行保护:获取二次打包后APK 的签名与正确的APK 签名做对比,判断 APK 程序是否进行过二次打包。
建议:客户端使用从属方证书进行签名后进行发布而不是使用第三方开发商的证书进行签名,以防开发商内部监管异常,证书滥用的情况出现。

4.2、组件导出安全

4.2.1、四大组件描述
Android 主要包含 4 大组件,分别是 activity 组件、 service 组件、 content provider 组件和 broadcast receiver 组件。
Activity 组件
( 1)一个Activity 通常就是一个单独的屏幕(窗口)。
( 2) Activity 之间通过Intent 进行通信。
( 3) android 应用中每一个Activity 都必须要在AndroidManifest.xml配置文件中声明,否则系统将不识别也不执行该Activity 。

Service 组件
( 1)service 用于在后台完成用户指定的操作。
( 2)开发人员需要在应用程序AndroidManifest.xml配置文件中声明全部的service,使用 标签。
( 3)Service 通常位于后台运行,它一般不需要与用户交互,因此Service 组件没有图形用户界面。Service 组件需要继承 Service 基类。 Service 组件通常用于为其他组件提供后台服务或监控其他组件的运行状态。

Content Provider 组件
( 1) android平台提供了Content Provider 使一个应用程序的指定数据集提供给其他应用程序。其他应用可以通过
ContentResolver 类从该内容提供者中获取或存入数据。
( 2)只有需要在多个应用程序间共享数据是才需要内容提供者。例如,通讯录数据被多个应用程序使用,且必须存储在一个内容提供者中。它的好处是统一数据访问方式。
( 3) ContentProvider 实现数据共享。ContentProvider用于保存和获取数据,并使其对所有应用程序可见。这是不

同应用程序间共享数据的唯一方式,因为android 没有提供所有应用共同访问的公共存储区。

broadcast receiver
( 1)你的应用可以使用它对外部事件进行过滤,只对感兴趣的外部事件(如当电话呼入时,或者数据网络可用时 ) 进行接收并做出响应。广播接收器没有用户界面。然而,它们可以启动一个activity 或 serice 来响应它们收到的信息, 或者用 NotificationManager来通知用户。通知可以用很多种方式来吸引用户的注意力,例如闪动背灯、震动、播放
声音等。一般来说是在状态栏上放一个持久的图标,用户可以打开它并获取消息。
( 2)广播接收者的注册有两种方法,分别是程序动态注册和AndroidManifest文件中进行静态注册。
( 3)动态注册广播接收器特点是当用来注册的Activity 关掉后,广播也就失效了。静态注册无需担忧广播接收器是
否被关闭,只要设备是开启状态,广播接收器也是打开着的。也就是说哪怕app 本身未启动,该app 订阅的广播在触发时也会对它起作用。
四大组件总结
( 1) 4 大组件的注册
4 大基本组件都需要注册才能使用,每个Activity 、service、Content Provider 都需要在 AndroidManifest 文件中进行配置。 AndroidManifest 文件中未进行声明的 activity 、服务以及内容提供者将不为系统所见,从而也就不可用。而
broadcast receiver 广播接收者的注册分静态注册(在AndroidManifest文件中进行配置)和通过代码动态创建并以调用 Context.registerReceiver() 的方式注册至系统。需要注意的是在AndroidManifest文件中进行配置的广播接收者会随系统的启动而一直处于活跃状态,只要接收到感兴趣的广播就会触发(即使程序未运行)。
( 2) 4 大组件的激活
内容提供者的激活:当接收到ContentResolver发出的请求后,内容提供者被激活。而其它三种组件 activity 、服务和广播接收器被一种叫做intent 的异步消息所激活。
4.2.2、组件安全检查方法

1、 AndroidManifest.xml 文件中 activity 组件里面有设置 android:exported 为 true ,表示此组件可以被外部应用调用。
2、 AndroidManifest.xml 文件中 activity 组件里面有设置 android:exported 为 false,表示此组件不可以被外部应用调用。只有同一个应用的组件或者有着同样
user ID 的应用可以
3、 AndroidManifest.xml 文件中 activity 组件里面没有设置android:exported属性,但是有intent -filter ,则 exported
默认属性为 true , true 表示此组件可以被外部应用调用。
4、AndroidManifest.xml 文件中 activity 组件里面没有设置 android:exported属性,也没有设置 intent -filter ,则 exported 默认属性为 false, false 表示此组件不可以被外部应用调用。只有同一个应用的组件或者有着同样user ID 的应用可以

备注:采用 drozer 工具可以进行检测组件是否存在导出风险
4.2.3、修复建议
1)如果应用的 Service 组件不必要导出,或者组件配置了 intent filter 标签,建议显示设置组件的 “ android:exported ” 属性为 false
2)如果组件必须要提供给外部应用使用,建议对组件进行权限控制

4.3、Webview漏洞

4.3.1、WebView 任意代码执行漏洞
4.3.1.1、 描述
出现该漏洞的原因有三个
WebView中addJavascriptInterface ()接口
WebView内置导出的searchBoxJavaBridge_对象
WebView内置导出的accessibility和accessibilityTraversalObject 对象

addJavascriptInterface 接口引起远程代码执行漏洞

JS调用Android 的其中一个方式是通过addJavascriptInterface 接口进行对象映射, 当 JS拿到 Android 这个对象后, 就可以调用这个Android 对象中所有的方法,包括系统类(java.lang.Runtime类),从而进行任意代码执行。

searchBoxJavaBridge_接口引起远程代码执行漏洞
在 Android 3.0 以下, Android 系统会默认通过searchBoxJavaBridge_的 Js接口给 WebView 添加一个 JS映射对象: searchBoxJavaBridge_对象
该接口可能被利用,实现远程任意代码。

accessibility 和accessibilityTraversal 接口引起远程代码执行漏洞问题类似以上
4.3.1.2、检测方法
addJavascriptInterface 接口引起远程代码执行漏洞 检查是通过 addJavascriptInterface 接口进行对象映射
searchBoxJavaBridge_接口引起远程代码执行漏洞
检查是否通过searchBoxJavaBridge_的 Js接口给WebView添加一个JS映射对象

accessibility 和accessibilityTraversal 接口引起远程代码执行漏洞问题类似以上
4.3.1.3、 修复建议
addJavascriptInterface接口引起远程代码执行漏洞
B1. Android 4.2 版本之后
Google在Android 4.2 版本中规定对被调用的函数以 @JavascriptInterface 进行注解从而避免漏洞 ×××

B2. Android 4.2 版本之前
在 Android 4.2 版本之前采用拦截 prompt ()进行漏洞修复。

searchBoxJavaBridge_接口引起远程代码执行漏洞删除 searchBoxJavaBridge_接口
// 通过调用该方法删除接口
removeJavascriptInterface ();

accessibility 和 accessibilityTraversal 接口引起远程代码执行漏洞删除 accessibility 和 accessibilityTraversal 接口

4.3.2、密码明文存储漏洞

4.3.2.1、描述
WebView 默认开启密码保存功能:
mWebView.setSavePassword(true)
开启后,在用户输入密码时,会弹出提示框:询问用户是否保存密码;
如果选择 ”是”,密码会被明文保到/data/data/com.package.name/databases/webview.db中,这样就有被盗取密码的危险
4.3.2.2、检测方法
方法 1、用户输入密码时看是否有弹出提示框,询问用户是否保存密码,如果有询问则表示存在漏洞,否则不存在。方法 2、检查代码中setSavePassword的值是否为 false。
4.3.2.3、修复建议关闭密码保存提醒

WebSettings.setSavePassword(false)

4.4、数据安全 – 本地敏感信息安全

4.4.1、APP所在目录的文件权限

4.4.1.1、 问题描述
测试客户端 APP 所在目录的文件权限是否设置正确,非 root 账户是否可以读,写,执行 APP目录下的文件。
4.4.1.2检测方法
采用 ls –l查看 app 目录的文件权限,其它组成员不允许读写权限。 Linux 文件权限为第一个为文件所有者对此文件的权限,第二个为所有者所在组的其它成员对此文件的权限,第三个为其他组成员对此文件的权限。
4.4.1.3修复建议
检查 App 所在的目录,其权限必须为不允许其他组成员读写

4.4.2、SQLite 数据库文件的安全性

4.4.2.1、 描述
SQLite,是一款轻型的数据库,是遵守 ACID 的关系型数据库管理系统.是开源的,高效率的, 可嵌入且程序驱动的数据库。
我们都知道,Android 系统内置了SQLite 数据库,并且提供了一整套的API 用于对数据库进行增删改查操作。数据
库存储是我们经常会使用到的一种存储方式,相信大多数朋友对它的使用方法都已经比较熟悉了吧。在 Android 中,我们既可以使用原生的 SQL语句来对数据进行操作, 也可以使用 Android API 提供的 CRUD方法来对数据库进行操作, 两种方式各有特点,选择使用哪一种就全凭个人喜好了。
不过,使用 SQLite 来存储数据却存在着一个问题。因为大多数的Android 手机都是Root 过的,而Root 过的手机都可以进入到 /data/data//databases 目录下面,在这里就可以查看到数据库中存储的所有数据。如果是一般的数据还
好,但是当涉及到一些账号密码,或者聊天内容的时候,我们的程序就会面临严重的安全漏洞隐患。
4.4.2.2、 检测方法
手机进行root 之后,查看 /data/data//databases 下的数据库文件是否包含敏感信息。
4.4.2.3、修复建议 重要信息进行加密存储

4.4.3、Logcat 日志

4.4.3.1、描述
检测客户端对应的 Logcat 日志是否会打印一些用户或服务器的敏感信息。
4.4.3.2、检测方法
通过 usb 连接手机,然后使用 adb logcat -v time > d:xx 的方式获取 logcat 信息或者使用 DDMS 工具查看 logcat 信息。
4.4.3.3、修复建议
具有敏感信息的调试信息开关一定要关闭。
对于安卓开发来讲,我们解决敏感信息问题就是对重要数据进行加密存储, log 日志不打印敏感信息。切记不要把账号密码等敏感信息保存在本地明文存储,如果一定要存储敏感信息务必进行加密存储重要信息。

4.4.4、敏感数据明文存储于Sdcard

4.4.4.1、描述
Android 提供了几种保存持久化应用数据的选择,其中之一就是外部存储( /sdcard, /mnt/sdcard )。外部存储包括设备内部的微型或标准大小的 SD 卡,挂载到 PC 上的 Android 设备存储卡以及 Android/obb 目录。
Android4.1 之前的版本,存放在外部存储的文件是 world -readable (能够被任何用户读取的)和 world -writable (能

够被任何用户写入) 。从 Android4.1 到 Android4.3 ,一个 app 想要写入外部存储的任意文件时,只需在 AndroidManifest
文件中声明 WRITE_EXTERNAL_STORAG权E限。但从 Android4.4 开始,引入了基于目录结构创建分组和文件模式,这
使得一个 app 在外部存储中的只能在以自己包名命名的目录下才具有文件的读写权限。非系统级的app 只允许在
Android/data/<package -name>/ 目录下操作。因此,每个 app 的文件读写权限被独立开来,不能互相访问。
上面描述的访问权限限制的不足,导致写入到外部存储的文件可能存在被同一设备上不同的app 修改和读取的风险
( Android4.4 之前版本)。
4.4.4.2、检测方法
查看是否有代码把内容写入到外部存储设备。
4.4.4.3、修复建议
在将文件保存到外部存储之前,先对文件内容进行加密。

4.5、键盘安全风险

4.5.1、键盘劫持测试

4.5.1.1、描述
安卓应用中的输入框默认使用系统软键盘,手机安装××后×, ××可×以通过替换系统软键盘,记录应用的密码。
4.5.1.2、检测方法
通过观察 app 在输入密码的地方是否会弹出自定义的软键盘。
4.5.1.3、修复建议
建议客户端开发自定义软键盘而不是使用系统软件盘以防止键盘劫持××。×

4.5.2、软键盘安全性测试

4.5.2.1、 描述
测试客户端是否使用随机布局的密码软键盘。
4.5.2.2、检测方法
用眼观察每次弹出来的自定义的软键盘是否随机变化布局
4.5.2.3、修复建议
建议客户端对自定义软键盘进行随机化处理,同时在每次点击输入框时都进行随机初始化。

4.6、屏幕录像测试

4.6.1、描述
测试通过连续截图,是否可以捕捉到用户密码输入框的密码。
4.6.2、检测方法
通过连续截图,是否可以捕捉到用户密码输入框的密码。
4.6.3、修复建议
建议客户端针对第三方或系统截屏编写抵抗逻辑, 例如屏蔽和截屏相关的函数或是当客户端处于进程栈顶层时将截屏图片用纯黑 ××片×对象进行覆盖。

4.7、界面劫持保护

4.7.1、界面劫描述
Activity 劫持是指当启动某个窗口组件时,被恶意应用探知,若该窗口界面是恶意程序预设的××对×象,恶意应用将启动自己仿冒的界面覆盖原界面,用户在毫无察觉的情况下输入登录信息,恶意程序在把获取的数据返回给服务端。

需要理解,Android 启动一个 Activity 时,是这样设计的,给Activity 加入一个标志位FLAG_ACTIVITY_NEW_TAS,K就能使它置于栈顶并立马呈现给用户。 但是这样的设计却有一个缺陷。如果这个Activity 是用于盗号的伪装 Activity 呢?

这种现象在 XcodeGhost 事件中,已经被证实是可以实现的。
在 Android 系统当中,程序可以枚举当前运行的进程而不需要声明其他权限,这样的话,就可以编写一个程序,启
动一个后台的服务,这个服务不断地扫描当前运行的进程,当发现目标进程启动时,就启动一个伪装的Activity 。如果这个 Activity 是登录界面,那么就可以从中获取用户的账号密码,具体的过程如下图:
4.7.2、界面劫持防护方法
作为一名移动应用开发者,要防御APP 被界面劫持,最简单的方法是在登录窗口等关键Activity 的onPause 方法中检测最前端Activity 应用是不是自身或者是系统应用。如果检测到不是自己,则弹出告警或者退出。
4.7.3、界面劫持案例
应用存在钓鱼劫持风险。应用程序没有做防钓鱼劫持措施,通过劫持应用程序的登录界面,可以获取用户的账号和密码,可能导致用户账号信息的泄露。

4.7.4、整改建议
应用程序自身通过获取栈顶activity ,判断系统当前运行的程序,一旦发现应用切换(可能被劫持),给予用户提示以防范钓鱼程序的欺诈。
获取栈顶activity (如下图),当涉及敏感activity (登录、交易等)切换时,判断当前是否仍留在原程序,若不是
则通过 Toast 给予用户提示。
使用 HTML5 架构或 android+HTML5 混合开发,实现登陆、支付等关键页面,降低被劫持的风险。

4.8、本地拒绝服务

4.8.1、漏洞描述
Android 系统提供了Activity 、Service 和 Broadcast Receiver 等组件,并提供了Intent机制来协助应用间的交互与通讯, Intent 负责对应用中一次操作的动作、动作涉及数据、附加数据进行描述,Android系统则根据此Intent 的描述,负责找到对应的组件,将Intent 传递给调用的组件,并完成组件的调用[1] 。Android 应用本地拒绝服务漏洞源于程序没有对 Intent.getXXXExtra() 获取的异常或者畸形数据处理时没有进行异常捕获,从而导致 ××者×可通过向受害者应用发送此类空数据、异常或者畸形数据来达到使该应用crash 的目的,简单的说就是××者×通过 intent 发送空数据、异

常或畸形数据给受害者应用,导致其崩溃。
本地拒绝服务漏洞影响范围:Android 系统所有版本
4.8.2、漏洞检测方法
使用 Android 扫描工具可以进行扫描。
4.8.3、 修复建议
本地拒绝服务漏洞修复建议:
1)将不必要的导出的组件设置为不导出
出于安全考虑, 应将不必要的组件导出, 防止引起拒绝服务, 尤其是杀毒、 安全防护、 锁屏防盗等安全应用 ; 在
AndroidMenifest.xml 文件中,将相应组件的 “ android:exported 属性设”置为 “ false如下”示,例: android:exported=“false”
2)intent 处理数据时进行捕获异常
建议处理通过 Intent.getXXXExtra()获取的数据时进行以下判断,以及用 try catch 方式进行捕获所有异常,以防止应用出现拒绝服务漏洞:
(1)空指针异常 ;
(2)类型转换异常 ;
(3)数组越界访问异常 ;
(4)类未定义异常 ;
(5)其他异常 ;

4.9、数据备份 allowBackup

4.9.1、漏洞描述
Android API Level 8及其以上 Android 系统提供了为应用程序数据的备份和恢复功能,此功能的开关决定于该应用
程序中 AndroidManifest.xml 文件中的 allowBackup 属性值,其属性值默认是True。当allowBackup标志为 true 时,用户即可通过 adb backup 和 adb restore 来进行对应用数据的备份和恢复,这可能会带来一定的安全风险。Android 属性 allowBackup 安全风险源于 adb backup 容许任何一个能够打开USB 调试开关的人从Android手机中复制应用数据到外设,一旦应用数据被备份之后,所有应用数据都可被用户读取;adb restore容许用户指定一个恢复的数据来源(即备份的应用数据)来恢复应用程序数据的创建。因此,当一个应用数据被备份之后,用户即
可在其他 Android 手机或模拟器上安装同一个应用,以及通过恢复该备份的应用数据到该设备上,在该设备上打
开该应用即可恢复到被备份的应用程序的状态。
尤其是通讯录应用,一旦应用程序支持备份和恢复功能,××者×即可通过 adb backup和 adb restore进行恢复新安装的同一个应用来查看聊天记录等信息;对于支付金融类应用,××者×可通过此来进行恶意支付、盗取存款等;因
此为了安全起见,开发者务必将allowBackup 标志值设置为false来关闭应用程序的备份和恢复功能,以免造成信息泄露和财产损失。

1、不在 AndroidManifest.xml 文件设置 allowBackup 属性值,其默认值为 true ,则应用可通过 adb 命令进行备份整个应用的数据
AndroidManifest.xml 文件内容:

android:label=“@string/app_name”>
<intent -filter>

</intent -filter>

2、在 AndroidManifest.xml文件显示设置allowBackup属性值为false,即 android:allowBackup=“false” ,则 Android 应用不可通过 adb 命令进行备份和恢复整个应用的数据
AndroidManifest.xml 文件内容:

<?xml version=”1.0″ encoding=”utf -8″?>

<intent -filter>

</intent -filter>

4.9.2、检测方法
查看 AndroidManifest.xml文件中是否有allowBackup ,如果没有则allowBackup 属性值, 默认allowBackup 值为 True, 则默认为可以备份应用数据,存在安全风险;如果allowBackup 属性值为false,则不可以备份应用数据。
4.9.3、修复方法
把 AndroidManifest.xml文件中allowBackup属性值设置为false。

4.10、Debug调试

4.10.1、描述
在准备发布应用之前要确保关闭debug 属性,即设置AndroidMainifest.xml中 android:debuggable=“false” ,false 表示关闭 debug 调试功能,true 表示开启debug 调试功能,但是有时候会忘记关掉这个属性。Debug 调试开启会存在应用被调试的风险。
4.10.2、检测方法
在发布之前最好进行测试,使用aapt 工具:
aapt list -v -a myfile.apk

这个命令将会打印和 apk 相关的所有详细信息,找到 “ android:debuggable”,它的值分为: 0x0: debuggable false
0xffffffff: debugabble true
例如,在我的测试中,这一行的信息是:
A: android ebuggable(0x0101000f)=(type 0x12)0x0
这说明我的 Release Build 已经关闭了debuggable !
4.10.3、修复建议 把 debuggable 关闭

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容