前言
随着运营商新技术新业务的发展,运营商层面对安全的要求有所变化,渗透测试工作将会面临内容安全、计费安全、业务逻辑及APP等方面的挑战。随着运营商自主开发的移动APP越来越多,这些APP可能并不会通过应用市场审核及发布,其中的安全性将面临越来越多的挑战。
在海量的APP应用中,可能会遇到各种各样的威胁:木马、病毒、篡改、破解、钓鱼、二次打包、信息泄露、资源篡改、信息劫持等。
为有效的针对上述各种威胁进行有效防范,保障运营商和客户的业务安全,本手册将着重从下表所列项目针对APP应用(安卓)安全进行检测。
APP应用安全测试要点(安卓) | |||
---|---|---|---|
客户端安全 | APK签名 | 进程和内存保护 | 内存访问和修改 |
反编译保护 | 动态注入 | ||
应用完整性校验 | 通信安全 | 通信加密 | |
组件安全 | 证书有效性 | ||
敏感信息安全 | 数据文件 | 关键数据加密和校验 | |
logcat日志 | 访问控制 | ||
密码安全 | 键盘劫持 | 客户端更新安全 | |
随机布局键盘 | 短信重放攻击 | ||
屏幕录像 | 业务安全 | 越权操作 | |
安全策略 | 密码复杂度检测 | 交易篡改 | |
账号登陆限制 | 重放攻击 | ||
账号锁定策略 | 用户枚举 | ||
密码问题验证 | 暴力破解 | ||
会话安全 | 注入/XSS/CSRF | ||
界面切换保护 | 其他 | ||
UI信息泄露 | |||
验证码安全 | |||
安全退出 | |||
密码修改验证 | |||
Activity界面劫持 |
表1 APP应用安全测试要点
第一章 测试环境
1.1 SDK
Java JDK 1.8.0_151,Android SDK。
1.2 工具
MobSF框架,GameGuardian(内存DUMP),夜神模拟器(运行环境模拟),Android Killer(反编译集成),改之理(反编译集成),7zip,dex2jar(文件转换),jd-gui,apktool,activity 劫持测试工具等,详细清单请参照附录。
第二章 客户端程序安全
2.1 安装包签名
2.1.1描述
在Android中,包名相同的两个APK会被认为是同一个应用。当新版本覆盖旧版本时,签名证书必须一致,否则会被拒绝安装(即使开启了“允许未知来源的应用”)。如果APK没有使用自己的证书进行签名,将会失去对版本管理的主动权。本项检测是检测客户端是否经过恰当签名(正常情况下应用都应该是签名的,否则无法安装),签名是否符合规范。
2.1.2测试步骤
打开cmd,进入到JDK的安装路径,C:Program FilesJavajdk1.8.0_111bin,输入命令:
代码语言:javascript复制jarsigner.exe -verify APK文件路径
测试结果如下:
图1 签名验证
如上图,如果证书指纹与客户一致,说明测试结果为安全。
检测签名的字段是否正确标示客户端程序的来源和发布者身份,输入命令:
代码语言:javascript复制jarsigner.exe -verify -verbose -certs APK文件路径
若各个字段与预期的一致,则测试通过
要说明的是,只有在使用直接客户的证书签名时,才认为安全。Debug证书、第三方(如开发方)证书等均认为存在风险。
2.1.3威胁等级
安装包签名的威胁等级判断一般如下:
若客户端安装包签名有异常(例如签名证书为第三方开发商而不是客户端发布方),此时高风险;若无异常则无风险。
2.1.4安全建议
将安装包进行签名并检测安装包签名的异常。
2.2 反编译保护
2.2.1描述
测试客户端安装程序,判断是否能反编译为源代码,java 代码和so 文件是否存在代码混淆等保护措施。未作保护的 java 代码,可以轻易分析其运行逻辑,并针对代码中的缺陷对客户端或服务器端进行攻击。
成功的反编译将使得攻击者能够完整地分析APP的运行逻辑,尤其是相关业务接口协议、和通信加密的实现。
2.2.2 名词解释
smali语言是一种Android系统特有的中间代码语言。Android系统使用Dalvik指令(可执行文件为.dex)代替了通常的JVM中间代码(可执行文件为.class、.jar)。对应Dalvik指令的“汇编语言”便是smali。因此,从.dex中恢复smali代码比恢复JAVA代码要容易,成功率更高。如果APK经过花指令处理,会导致无法恢复smali代码(表现为apktool解包失败)。
花指令:由设计者特别构思,希望使反汇编的时候出错,让破解者无法清楚正确地反汇编程序的内容,迷失方向。经典的应用,目标位置是另一条指令的中间,这样在反汇编的时候便会出现混乱。
2.2.3 测试步骤
把apk当成zip并解压(后缀改为zip),得到classes.dex文件(有时可能不止一个dex文件,文件名均以classes*开头),如下图:
图2 APK文件结构
使用dex2jar执行如下命令:
代码语言:javascript复制dex2jar.bat classes.dex 文件路径
得到classes.dex.jar,然后使用jd-gui打开jar文件,即可得到JAVA代码。或者直接使用smali2java打开apk文件,也可反编译回Java代码。
图3 反编译后的APK
有时用apktool能够解包并查看smali,但dex2jar却不行。如果dex2jar反编译失败,可以试试看能不能恢复smali代码。
如上图,逆向后发现是没混淆的情况,是不安全的。
如果代码经过混淆,或者有加壳措施,不能完整恢复源代码的,都可以认为此项安全。
下图为混淆后的代码样例:
图4 有混淆的代码
2.2.4威胁等级
若客户端进行加固保护,此时认为无风险。
若大部分代码(包括核心代码)经过混淆,此时低风险。
若部分代码混淆,关键代码(加密或通信等)可以获知其关键代码,此时中风险。
2.2.5安全建议
建议客户端程序可以把关键代码以 JNI 方式放在 so 库里。so 库中是经过编译的arm 汇编代码,可以对其进行加壳保护,以防止逆向分析。
第三章 应用完整性校检
3.1描述
测试客户端程序是否对自身完整性进行校验。攻击者能够通过反编译的方法在客户端程序中植入自己的木马,客户端程序如果没有自校验机制的话,攻击者可能会通过篡改客户端程序窃取手机用户的隐私信息。
3.2测试步骤
用ApkTool将目标APK文件解包,命令如下;
java -jar apktool.jar d -f apk文件路径 -o 解包目标文件夹
图5 解包后的APK资源目录
随便找一个解包目录里的资源文件进行修改,推荐找到splash.png进行修改(容易确认结果);将APK拖入Androidkiller,搜索splash.png,修改替换,,然后签名打包回APK。
将签了名的APK安装、运行、确认是否存在自校验;需要注意的是,如果之前安装的APK和修改后的APK签名不同,就不能直接覆盖安装,一般来说,先卸载之前安装的APP即可。
注:APK必须进行签名后,方可安装和运行。如果开启了“允许未知来源的应用”,那么Debug证书、自签名证书、过期证书的签名都是可以的,但是不可以不签名。
将客户端程序文件反编译,修改源码或资源文件后重新打包安装运行如果可运行,说明文件完整。
3.3威胁等级
若应用完整性校验不使用MANIFEST.MF 中的数据,且核心代码通过 JNI 技术写入.so库,同时于服务端进行相关校验,此时无风险。
若应用完整性于本地进行验证而不存在其他问题或使用 MANIFEST.MF 中的数据作为验证凭证(有新文件时提示应用完整性验证失败),此时低风险;
若在本地进行验证的基础上只通过MANIFEST.MF 对客户端原有文件进行校验而忽略新增文件的检验,此时中风险;若未进行应用完整性校验此时高风险。
3.4安全建议
建议客户端在每次开机启动时进行客户端自身的应用完整性校验,在验证逻辑中不使用MANIFEST.MF中的数据作为验证凭证,同时需验证是否有不属于该客户端版本的新文件添加,验证过程于服务器端完成。
第四章 组件安全
4.1描述
本项主要测试客户端是否包含后台服务、Content Provider、第三方调用和广播等组件,Intent 权限的设置是否安全。应用不同组成部分之间的机密数据传递是否安全。检查客户端是否存在组件劫持风险,查看客户端程序具有导出哪些应用信息的权限。反编译APK文件后,检查AndroidManifest文件中是否有多余的android:export声明,客户端是否存在导出其他应用信息的权限等。
4.2名词解释
1.组件:安卓APP以组件为单位进行权限声明和生命周期管理;
2.组件的作用:安卓系统的组件共有四种,其主要用途分别为:
Activity:呈现可供用户交互的界面,是最常见的组件; Service:长时间执行后台作业,常见于监控类应用; Content Provider:在多个APP间共享数据,比如通讯录数据; Broadcast Receiver:注册特定事件,并在其发生时被激活;
3.权限声明:安卓系统定义了许多权限声明项,分别对应一些操作系统功能;
4.权限声明的作用:如果一个APP或组件在没有声明权限的情况下就调用相关API,会被拒绝访问;但如果声明了相关权限,安装的时候就会有提示;
5.组件导出:简而言之,就是别的APP也可以访问这个组件。
6.组件导出的作用:有些APP的功能需要提供一些接口给其它APP访问,就需要把相关的接口功能放在一个导出的组件上。
7.组件导出的危害:因为权限声明是以组件为单位的,A组件调用B组件的功能来访问操作系统API时,适用于B组件的权限声明。
如果B作为导出组件,没有进行严格的访问控制,那么A就可以通过调用B来访问原本没有声明权限的功能,构成本地权限提升。
4.3测试步骤
4.3.3方案一:
使用ApkTool解包,打开解包目录中AndroidManifest.xml,对其中声明的各个组件,根据以下规则判断是否可导出:
1.显示声明了android:exported=”true”,则可导出;
2.显示声明了android:exported=”false”,则不可导出;
3.未显示声明android:exported:
代码语言:javascript复制a) 若组件不是Content Provider:
i. 若组件包含则可导出,反之不可;
代码语言:javascript复制b) 若组件是Content Provider:
i. 若SDK版本<17则可导出,反之不可。
从测试的角度上,只能判断组件是否导出,但能否构成危害需要详细分析源代码后才能得出结论。一般来说,在测试时尽管写清所有的导出组件,由客户开发侧确认相关组件是否确实需要导出即可。
图6 安全的组件导出示例
由于功能需要,启动Activity和ContentProvider大多是导出组件,一般无须理会。如上图的组件导出就是安全的。
4.3.4 方案二:
检查 AndroidManifest.xml 文件中各组件定义标签的安全属性是否设置恰当。如果组件无须跨进程交互,则不应设置 exported 属性为 true。例如,如下图所示,当 MyService 的 exported属性为 true 时,将可以被其他应用调用。(当有设置权限(permissions)时,需要再考察权限属性。如 android:protectionLevel 为 signature 或 signatureOrSystem 时,只有相同签名的 apk才能获取权限。
图7 可调用的组件
可以使用“组件安全测试工具”来检测组件的 exported 属性(有些应用在代码中动态注册组件,这种组件无法使用“组件安全测试工具”测试,需要通过阅读代码确定是否安全。
凡是列出来的组件都是 exported 属性为true 的。
当发现有可利用的组件导出时,(当然,并不是说所有导出的组件都是不安全的,如果要确定,必须看代码,对代码逻辑进行分析)可利用drozer测试工具进行测试。
4.4威胁等级
若不存在组件暴露的情况,此时无风险。
如存在组件暴露的情况,但暴露的组件无关客户端逻辑核心或不会泄露用户敏感信息,此时低风险;若暴露的组件会泄露用户敏感信息(例如邮件客户端存在消息组件的暴露,攻击者可以通过编写 APK,通过组件利用的方式读取用户邮件信息)。
4.5安全建议
避免不必要的组件导出。
第五章 敏感信息安全
5.1数据文件
5.1.1 描述
检测客户端是否保存明文敏感信息,能否防止用户敏感信息的非授权访问。
文件敏感信息泄露以明文存储“记住密码”居多。
5.1.2 测试步骤
首先查看相关文件的权限配置。正常的文件权限最后三位应为空(类似“rw-rw——”),即除应用自己以外任何人无法读写;目录则允许多一个执行位(类似“rwxrwx—x”)。如下图所示,(lib 子目录是应用安装时由 android 系统自动生成,可以略过):
图8 文件的权限
当客户端使用MODE_WORLD_READABLE 或MODE_WORLD_WRITEABLE 模式创建文件时,shared_prefs 目录下文件的权限也会多出一些,这不一定是安全问题,如下图(Google已不推荐使用这些模式):
图 9 不推荐的文件权限模式
权限检测完整后,再检查客户端程序存储在手机中的 SharedPreferences 配置文件,通常是对本目录下的文件内容(一般是xml)进行检查,看是否包含敏感信息。
使用数据库查看工具即可查看这些文件中是否有敏感信息(sqllite等)。
还有些时候,客户端程序 apk 包中也是是保存有敏感信息的,比如检查 apk 包中各类文件是否包含硬编码的的敏感信息等。如下图APP的相关编码信息:
图10 包含敏感代码的APK
5.2 威胁等级
根据敏感信息泄露的程度进行威胁等级评分。若私有目录中存在存储了用户登陆密码(明文或只进行过一次单项哈希散列),手势密码(明文或只进行过一次单项哈希散列)或曾经访问过网址的 Cookie 等敏感信息的文件,此时为高风险,若不存在则无风险。
5.3 安全建议
尽量避免在文件、数据库、日志等位置写入敏感信息。如果确实需要存储,应当进行加密。对于内存中的信息泄露,可以通过反注入、反调试来解决。
此外,正常的文件权限最后三位应为空(类似“rw-rw——”),目录则允许多一个执行位(类似“rwxrwx—x”)。
5.4 Logcat日志
5.4.1 描述
本项主要是检查客户端程序存储在手机中的日志是否含有敏感信息。
5.4.2 测试步骤
将内存DUMP到SD卡,然后用adb到主机上查看。
使用adb工具连接设备:
adb devices //**查看安卓设备列表** adb -s **设备名称 其它命令 //当连接了多个设备时,选择操作的目标设备,否则会出错** adb pull **手机目录名 PC目录名 //从安卓设备中复制文件到电脑中**
然后使用WinHex打开
图11 查看遗留内存信息
这是查看内存遗留的信息,还可以直接使用adb查询logcat日志,在adb shell中,有下列命令可用:
logcat //**持续输出日志,直到Ctrl C** logcat-d //**一次性输出日志缓存,不会阻塞** logcat-c //**清空日志缓存**
5.4.3 威胁等级
根据敏感信息泄露的程度进行威胁等级评分。若相关信息中存在存储了用户登陆密码(明文或只进行过一次单项哈希散列),手势密码(明文或只进行过一次单项哈希散列)或曾经访问过网址的 Cookie 等敏感信息,此时为高风险,若不存在则无风险。
5.4.4 安全建议
数据传输应做到加密处理,敏感信息不应输出在logcat日志中。
第六章 密码安全
6.1 键盘劫持
6.1.1 描述
测试客户端程序在密码等输入框是否使用自定义软键盘。安卓应用中的输入框默认使用系统软键盘,手机安装木马后,木马可以通过替换系统软键盘,记录手机键盘输过的密码。
6.1.2 测试步骤
通常来说,只有使用系统输入法的编辑框才能够进行键盘码记录。如果是自制的软键盘,则可以尝试进行触摸屏记录。不使用系统输入法,且按键随机分布的软键盘是安全的。
6.1.3 威胁等级
能够劫持键盘风险为高,不能则为无风险。
6.1.4 安全建议
尽量使用系统自定义的随机软键盘(而非系统输入法)来输入敏感信息。或者对Native层输入记录功能进行Hook(需要root权限)。
6.2 随机布局软键盘
6.2.1 描述
测试客户端实现的软键盘,是否满足键位随机布放要求。
6.2.2 测试步骤
人工观测键位分布是否为随机布放。
6.2.3 威胁等级
当客户端软键盘未进行随机化处理时为低风险;当客户端软键盘只在某一个页面载入时,初始化一次而不是在点击输入框时重新进行随机化也为低风险。
6.2.4 安全建议
键位随机布放。
6.3 屏幕录像
6.3.1 描述
客户端使用的随机布局软键盘是否会对用户点击产生视觉响应。当随机布局软键盘对用户点击产生视觉响应时,安卓木马可以通过连续截屏的方式,对用户击键进行记录,从而获得用户输入。
6.3.2 测试步骤
使用ADB进行测试:
adb shell /system/bin/screencap -p 输出png路径(安卓设备中)
如图:
图12 截屏并生成文件
在/mnt/sdcard/路径下,可以看到1a.png:
图13 生成的png截图文件
打开:
图14 浏览截屏图片内容
攻击者可以在用户进入登录页面,在输入密码的同时,进行连续截图,即可记录用户输入的密码。如果没有防截屏,那么即使是随机分布的、没有视觉反馈的软键盘也会被记录:
还有一种验证方式是从代码方面进行验证:
检测需较高安全性的窗口(如密码输入框),看代码中在窗口加载时是否有类似下图的代码。按照 android SDK的要求,开启 FLAG_SECURE 选项的窗口不能被截屏。
图15 FLAG_SECURE选项
6.3.3 威胁等级
当使用第三方程序(或系统截屏)可以对客户端内容进行截屏时,为中风险;当客户端会对截屏操作进行有效抵抗时(无法截屏或截屏结果为黑屏等无意义图片)无风险。
6.3.4 安全建议
在敏感信息的输入过程尽量避免视觉反馈,或者在操作系统层面对截屏相关功能进行Hook以阻止敏感信息输入期间其它程序的截屏操作(需要root权限)。
6.4手势密码
6.4.1 描述
主要从手势密码的复杂度、修改和取消、本地信息保存、锁定策略、抗攻击测试等方面进行测试。
6.4.2 测试步骤
手势密码的复杂度:
- 进入客户端设置手势密码的页面进行手势密码设置。
- 进行手势密码设置,观察客户端手势密码设置逻辑是否存在最少点位的判断。
- 反编译 APK 为 jar 包,通过jd-gui观察对应代码逻辑是否有相应的判断和限制条件。(一般设置手势密码若输入点数过少时会有相应的文字提示,通过此文字提示可以快速定位到代码位置)
手势密码的修改和取消:
- 进入客户端设置手势密码的位置,一般在个人设置或安全中心等地方。
- 进行手势密码修改或取消操作,观察进行此类操作时是否需要输入之前的手势密码或普通密码。
- 观察在忘记手势密码等其他客户端业务逻辑中是否存在无需原始手势或普通密码即可修改或取消手势密码的情况。
- 多次尝试客户端各类业务,观察是否存在客户端逻辑缺陷使得客户端可以跳转回之前业务流程所对应页面。若存在此类逻辑(例如手势密码设置),观察能否修改或取消手势密码。
- 反编译 APK 为 jar 包,通过jd-gui观察对应代码逻辑,寻找客户端对于手势密码的修改和删除是否存在相应的安全策略。
手势密码的本地信息保存:
- 首先通过正常的操作流程设置一个手势密码并完整一次完整的登陆过程。
- 寻找/data/data 的私有目录下是否存在手势密码对应敏感文件,若进行了相关的信息保存,基本在此目录下。(关键词为 gesture.key 等)
- 若找到对应的文件,观察其存储方式,为明文还是二进制形式存储,若为二进制形式,观察其具体位数是否对应进行 MD5(二进制 128 位,十六进制32位或 16 位)、SHA-1(二进制 160 位,十六进制 40 位)等散列后的位数。如果位数对应,即可在反编译的 jar包中搜索对应的关键字以迅速对应代码。
- 通过代码定位确认其是否进行了除单项哈希散列之外的加密算法,若客户端未将手势密码进行加密或变形直接进行散列处理可认为其不安全,一是因为现阶段 MD5、SHA-1 等常用的哈希算法已被发现碰撞漏洞,二是网络中存在 www.somd5.com 等散列值查询网站可以通过大数据查询的方式获取散列前的明文手势密码。
手势密码的锁定策略:
- 首先通过正常的操作流程设置一个手势密码。
- 输入不同于步骤 1 中的手势密码,观察客户端的登陆状态及相应提示。若连续输入多次手势密码错误,观察当用户处于登陆状态时是否退出当前的登陆状态并关闭客户端;当客户未处于登录状态时是否关闭客户端并进行一定时间的输入锁定。
- 反编译 APK 为 jar 包,通过jd-gui观察对应代码逻辑,寻找客户端是否针对输入次数及锁定时间有相应的逻辑处理。
手势密码的抗攻击测试:
- 下载并安装 Xposed 框架及 SwipeBack 插件。
- 启动客户端并进入手势密码输入页。
- 启动 SwipeBack 插件,观察是否可以通过滑动关闭手势密码输入页的方式进入登陆后的页面。
6.4.3 威胁等级
手势密码的复杂度:
当用户设置或修改手势密码时服务器会对手势密码安全性(使用点数)进行判断时无风险,否则低风险。
修改和取消:
当取消或修改手势密码时,如果不会验证之前的手势密码则为中风险;若存在验证则无风险。
本地信息保存:
当本地保存了明文存储(数组形式)的手势密码时为高风险;当本地保存了只进行单项哈希散列的手势密码时为中风险。
锁定策略:
当服务器不会验证手势密码输入错误次数时为中风险,会进行验证时无风险。
抗攻击测试:
若客户端采用附着的方式将手势密码放置于登陆后的界面上时,如果无法抵抗SwipeBack 插件的滑动攻击则高风险,如果可以抵抗则无风险。
6.4.4 安全建议
上述手势密码哪方面出现问题就根据哪方面的风险提出针对性的建议。
第七章 安全策略
安全策略在实际测试中受限较多,因此建议的风险等级:安全策略类全部为低危。
7.1 密码复杂度检测
7.1.2 描述
测试客户端程序是否检查用户输入的密码强度,禁止用户设置弱口令。
7.1.3 测试步骤
人工测试,尝试将密码修改为弱口令,如:123456,654321,121212,888888 等,查看客户端是否拒绝弱口令。也可以阅读逆向后的客户端 java 代码,寻找对用户输入口令的检查方法。
7.1.4 威胁等级
低危。
7.1.5 安全建议
当系统允许用户设置弱密钥时为低风险,如果存在系统存在一定的安全策略(使用数字,大小写字母,下划线,特殊字符组合,且至少为 8位)时无风险。
7.2 账号登陆限制
7.2.1 描述
测试一个帐号是否可以同时在多个设备上成功登录客户端,进行操作。
7.2.2 测试步骤
人工测试。
7.2.3 威胁等级
低危。
7.2.4 安全建议
禁止同一个账号可以同时在多台移动终端设备上登陆。
7.3 账户锁定策略
7.3.1 描述
测试客户端是否限制登录尝试次数。防止木马使用穷举法暴力破解用户密码。
7.3.2 测试步骤
人工测试。
7.3.3 威胁等级
低危。
7.3.4安全建议
设定账户锁定策略。
7.4 问题验证
7.4.1 描述
测试对账号某些信息(如单次支付限额)的修改是否有私密问题验证。私密问题验证是否将问题和答案一一对应。私密问题是否足够私密。
7.4.2 测试步骤
人工测试。
7.4.3 威胁等级
当用户进行忘记密码操作时,在发送邮件给用户邮箱前是否进行私密问题的验证,若验证则无风险;若不验证则低风险。
7.4.4 安全建议
对于敏感功能操作时,要进行私密问题验证。
7.5 会话安全
7.5.1 描述
测试客户端在超过 20 分钟无操作后,是否会使会话超时并要求重新登录。超时时间设置是否合理。
7.5.2 测试步骤
人工测试。
7.5.3 威胁等级
当系统不存在会话超时逻辑判断时为低风险,若存在则无风险。
7.5.4 安全建议
设置会话超时。
7.6 界面切换保护
7.6.1 描述
检查客户端程序在切换到其他应用时,已经填写的账号密码等敏感信息是否会清空,防止用户敏感信息泄露。
如果切换前处于已登录状态,切换后一定时间内是否会自动退出当前会话。
7.6.2 测试步骤
人工检测。
在登录界面(或者转账界面等涉及密码的功能)填写登录名和密码,然后切出,再进入客户端,看输入的登录名和密码是否清除。登录后切出,5 分钟内自动退出为安全。
7.6.3 威胁等级
当移动终端设备进行进程切换操作,显示界面不为客户端页面时,若客户端提示用户确认是否为本人操作,则无风险;若无相应提示则为低风险。
7.6.4 安全建议
对于画面切换进行提示或者验证。
7.7 UI信息泄露
7.7.1 描述
检查客户端的各种功能,看是否存在敏感信息泄露问题。
7.7.2 测试步骤
人工测试。使用错误的登录名或密码登录,看客户端提示是否不同。在显示卡号等敏感信息时是否进行部分遮挡。
7.7.3 威胁等级
若在用户名输入错误和密码输入错误时提示信息不同则存在 UI 信息泄露问题,此时为低风险,否则无风险。
7.7.4 安全建议
注意UI信息的防护。
7.8 验证码安全
7.8.1 描述
测试客户端在登录和交易时是否使用图形验证码。验证码是否符合如下要求:由数字和字母等字符混合组成;采取图片底纹干扰、颜色变换、设置非连续性及旋转图片字体、变异字体显示样式等有效方式,防范恶意代码自动识别图片上的信息;具有使用时间限制并仅能使用一次;验证码由服务器生成,客户端文件中不包含图形验证码文本内容。
7.8.2 测试步骤
观察验证码组成,若简单,可以尝试使用PKAVHttpFuzzer的验证码识别工具进行识别:
图16 验证码识别工具
7.8.3 威胁等级
当图形验证码由本地生成而不是从服务器获取时为中风险;当验证码安全性低或不存在验证码时为中风险;不存在以上两个问题时无风险。
7.8.4 安全建议
加强验证码的识别难度,对于验证码的验证做到“一次一验”。
7.9 安全退出
7.9.1 描述
测试客户端退出时是否正常终止会话。
7.9.2 测试步骤
检查客户端在退出时,是否向服务端发送终止会话请求。客户端退出后,还能否使用退出前的会话 id 访问登录后才能访问的页面。
7.9.3 威胁等级
若客户端退出登录时不会和服务器进行Logout的相关通信则为中风险,否则无风险。
7.9.4 安全建议
客户端退出时要做到和服务器进行Logout的相关通信。
7.10 密码修改验证
7.10.1描述
测试客户端在修改密码时是否验证旧密码正确性。
7.10.2 测试步骤
人工测试。
7.10.3威胁等级
当进行密码修改时是否要求输入原密码已验证其正确性,若需要输入则无风险;如不需输入原密码则中风险。
7.10.4 安全建议
修改密码需要验证原密码的正确性。
7.11 Activity界面劫持
7.11.1 描述
检查是否存在 activity 劫持风险,确认客户端是否能够发现并提示用户存在劫持。
7.11.2 测试步骤
安装HijackActivity.apk,使用 activity 界面劫持工具,在工具中指定要劫持的应用进程名称。如图所示,从列表中选择被测试的应用,点击 OK。打开应用,测试工具会尝试用自己的窗口覆盖被测的应用。
图17 HijackActivity.apk劫持工具
如果劫持成功,会出现如下界面:
图18 成功劫持
7.11.3 威胁等级
若客户端无法抵抗 Activity 界面劫持攻击时为中风险;若可以抵抗攻击则无风险。
7.11.4 安全建议
Activity劫持通常依靠注册Receiver响应android.intent.action.BOOT_COMPLETED事件。客户端程序可以在启动前检查Receiver并报警;
由于Activity界面劫持攻击通常是将自己的页面附着在客户端之上,因此需要进行界面切换操作,因此在界面切换到后台时弹出警告信息也可以达到一定的效果。
除此之外,因为Android进程栈的工作原理,建议开发客户端时针对进程栈进行相应的保护,可禁止其他进程放置于客户端之上。
第八章 进程保护
8.1 内存访问和修改
8.1.1 描述
通过对客户端内存的访问,木马将有可能会得到保存在内存中的敏感信息(如登录密码,帐号等)。测试客户端内存中是否存在的敏感信息(账号、明文密码等等)。
8.1.2 测试步骤
需要 root 权限,可以使用 MemSpector 查看、搜索和修改客户端内存数据。用户名、密码等数据通常会在/dev/ashmem/dalvik-heap 内存段。(目前大多数工具都是通过ptrace接口修改客户端内存,可以使用 ptrace 机制本身防护。)
8.1.3 威胁等级
当进行敏感操作后在内存中可以搜索到用户输入的敏感信息时为高风险,否则无风险。
8.1.4 安全建议
对于内存中的信息泄露,可以通过反注入、反调试来解决。
8.2 动态注入
8.2.1 描述
通过注入动态链接库,hook 客户端某些关键函数,从而获取敏感信息或者改变程序执行。
8.2.2 测试步骤
使用工具动态注入应用进程内存。Dynamic Dalvik Instrumentation Toolkit或者使用 hook 框架来进行测试。
8.2.3 威胁等级
当客户端存在动态注入隐患时高风险,否则无风险。
8.2.4 安全建议
防止应用程序被Hook。
第九章 通信安全
9.1 通信加密
9.1.1 描述
如果客户端与服务器之间的通信加密协议实现不当,攻击者将有机会对当前网络环境中其他合法用户的通信内容进行窃听甚至篡改。
9.1.2 测试步骤
为了对服务器端进行测试,至少要先弄清楚客户端与服务器的通信协议。
一般来说,有以下三种情况:
1. 如果使用HTTP(S)协议,大多可以通过设置系统HTTP代理来进行操作客户端的网络访问。这种情况占绝大多数:
代码语言:javascript复制
a) 在电脑上开启Burpsuite/Fiddler等代理工具,并设置允许远程连接;
b) 如果是真实手机:
i. 使用netsh wlan开启承载网络(具体方法请自行百度);
ii. 用手机连接电脑的WIFI,其余部分同Genymotion。
- 如果是HTTP(S)协议,但是不接受操作系统代理:
代码语言:javascript复制
a) 如果设备已经root,可以安装 “ProxyDroid” APP;
b) 如果设备不能root,可以把安卓虚拟机装在Windows虚拟机里,在Windows虚拟机上安装Proxifier,挂到物理机的代理工具上;
- 如果不是HTTP协议:
代码语言:javascript复制
a) 那么一般就是由TCP或UDP实现的私有协议,大多数是TCP;
b) 虽然也可以用一些办法来操作TCP网络访问(比如用WPE附加到Emulator的进程上),但由于TCP是全双工流式协议,传输层上没有明确的报文边界。如果私有协议是请求-响应式的还勉强可以编辑,如果是委托-回调式,或者其它复杂形式的协议,使用通用工具进行操作是非常困难的。
c) 这种情况可以通过Wireshark抓包分析,如果协议不复杂,可以自行实现代码进行仿制;
d) 如果协议复杂,就需要对APP的代码进行分析,找到通信的部分,将其摘出并调用,或者自行实现代码进行仿制;
此外,通信过程如果有加密、签名等措施,通常需要从客户端代码入手,进行传统逆向分析以破解其加密。如果其实现非常复杂,此项可以认为安全。
逆向分析的常见入手位置主要有数据(字符串内容等)和特定API(如界面、网络、文件、Native操作等)两种。
有时会遇到客户端检查了HTTPS证书的情况(表现为,代理工具如果不替换SSL证书则正常代理,替换SSL证书则客户端网络异常),会有以下两种情况:
- 客户端使用操作系统证书链验证服务端证书: a) 此种情况下,可以从代理工具中导出证书,然后安装到安卓设备中。
- 客户端预存了服务端证书的公钥或Hash,甚至整个证书: a) 此种情况下,如果客户端本身缺少完整性校验,可以尝试分析其代码,并修改其存储的证书信息为代理工具的证书信息;
所有需要对客户端程序/设备进行操作后,才能解除的保密性或完整性措施,不算作风险。
加密签名措施的破解,最终还是要根据客户端的具体实现方式进行分析。
9.1.3 威胁等级
当客户端和服务器的通信不经过 SSL 加密(或没有参考 TLS 协议,RF**346 等实现加密信道)时为高风险;当自实现通信算法存在漏洞可被解析或绕过时为高风险;使用低版本SSL 协议(SSLV2,SSLV3 均存在漏洞,至少使用 TLSV1.1 以上算法)时为高风险;以上问题均不存在时无风险。
9.1.4 安全建议
建议使用SSL协议,并在客户端对服务端的证书进行验证。如果自行实现加密协议,建议在客户端预先存储服务端公钥,在建立会话时随机生成对称加密密钥,用服务端公钥加密并发送给服务端,随后服务端用私钥解密后,正式开始进行通信。加密过程尽量避免使用CBC模式。
9.2 证书有效性
9.2.1 描述
主要测试SSL 协议安全性、SSL证书验证等。
9.2.2 测试步骤
首先测试客户端程序是否严格检查服务器端证书信息。
通过修改 DNS,将客户端链接到的主页地址改为 https://mail.qq.com/,然后使用客户端访问服务端,查看客户端是否会提示连接错误。此项测试主要针对客户端是否对 SSL 证书中的域名进行确认。
也可以查阅代码中是否有 SSL 验证。
如下图相关验证:
图19 SSL验证
还需要检测SSL 协议安全性。主要是检测客户端使用的 SSL 版本号是否不小于 3.0(或 TLS v1),加密算法是否安全。(安全规范要求)。
测试命令如下:
代码语言:javascript复制Openssl s_client -host 测试网址 -port 443
图20 测试结果
9.2.3 威胁等级
当客户端和服务器互相不验证证书时高风险,当只有客户端验证服务器证书时为中风险;
当服务器不通过白名单的方式验证客户端时为中风险;当客户端和服务器进行双向认证,并且服务器通过白名单方式验证客户端证书时无风险。
9.2.4 安全建议
使用Https方式进行加密,且服务器通过白名单方式验证客户端证书。
9.4 关键数据加密和校检
9.4.1 描述
测试客户端程序提交数据给服务端时,密码、收款人信息等关键字段是否进行了加密,防止恶意用户嗅探到用户数据包中的密码等敏感信息。
9.4.2 测试步骤
在手机上配置好代理,观察客户端和服务端的交互数据。检查关键字端是否加密。
如果客户端对根证书进行了严格检测,导致代理无法使用。则可以将代理的根证书安装到设备上,使根证书可信。或是替换客户端apk 中的根证书文件。如果上述方法均失效,则反编译为 java 代码,将客户端逆向后,通过阅读java 代码的方式寻找客户端程序向服务端提交数据的代码,检查是否存在加密的代码。
9.4.3 威胁等级
当账号,密码,卡号等数据明文传输,未进行二次加密时为高风险;当密码只进行了单项散列而未经过加密时为高风险;当返回数据中包含更新的 URL 且数据不加密时为高风险;
当校验字段删除后服务器仍会处理所发送的数据包时为高风险;当校验字段的散列中不包含随机因子时为高风险。以上问题均不存在时无风险。
9.4.4 安全建议
对于重要的敏感信息传输时要进行严格的加密和校检。
9.5 访问控制
9.5.1 描述
测试客户端访问的 URL 是否仅能由手机客户端访问。是否可以绕过登录限制直接访问登录后才能访问的页面,对需要二次验证的页面(如私密问题验证),能否绕过验证。
9.5.2 测试步骤
人工测试。在 PC 机的浏览器里输入 URL,尝试访问手机页面。
9.5.3 威胁等级
当 PC 端也可访问手机页面时低风险,当可以绕过登陆限制访问登陆后才能访问的页面时中风险。
9.5.4 安全建议
对也页面访问权限进行严格控制。
9.6 客户端更新安全性
9.6.1 描述
测试客户端自动更新机制是否安全。如果客户端更新没有使用官方应用商店的更新方式,就可能导致用户下载并安装恶意应用,从而引入安全风险。
9.6.2 测试步骤
使用代理抓取检测更新的数据包,尝试将服务器返回的更新 url 替换为恶意链接。看客户端是否会直接打开此链接并下载应用。在应用下载完毕后,测试能否替换下载的 apk 文件,测试客户端是否会安装替换后的应用。
9.6.3 威胁等级
当客户端返回明文 URL 地址并可以通过篡改的方式控制用户下载恶意 APK包进行安装,则高风险;若返回数据包经过二次加密则无风险。
9.6.4 安全建议
对于返回的数据包要进行二次加密处理。
9.7 短信重放攻击
9.7.1 描述
检测应用中是否存在数据包重放攻击的安全问题。是否会对客户端用户造成短信轰炸的困扰。
9.7.2 测试步骤
尝试重放短信验证码数据包是否可以进行短信轰炸攻击。
9.7.3 威胁等级
当存在短信轰炸的情况时为中风险,若短信网关会检测短时间内发送给某一手机号的短信数量则无风险。
9.7.4 安全建议
对于验证码的发送要进行相关身份验证,如:验证码。
第十章 业务安全
业务安全基本上检测的业务逻辑安全。对于业务逻辑安全在进行测试的时候可以参考业务逻辑渗透测试思维导图:
图21 业务逻辑渗透测试思维导图
手机APP的业务安全和WEB测试并无太大差别,仅做简单说明。
10.1 越权操作
10.1.1 描述
服务器端对客户提出的数据操作请求过分信任,忽略了对该用户操作权限的判定,导致攻击账号拥有了其他账户的增删改查功能。
10.1.2 测试步骤
属于业务逻辑相关的测试,因此需要手工测试。
10.1.3 威胁等级
根据越权操作的危害性进行定级。
10.1.4 安全建议
1、基础安全架构,完善用户权限体系。要知道哪些数据对于哪些用户,哪些数据不应该由哪些用户操作;
2、鉴权,服务端对请求的数据和当前用户身份做校验;
10.2 交易篡改
10.2.1 描述
本项测试主要是修改金额信息(如:转帐金额为负值),订单信息(如:订单的数量)等。
10.2.2 测试步骤
手工抓包测试。
10.2.3 威胁等级
高(此项业务一般为核心业务,只要能修改相关信息,基本上都是高危漏洞)。
10.2.4 安全建议
服务端要做到严格的验证。(根据业务情形不同,安全建议也不相同,因此这里只能简单的一句话描述)。
10.3 重放攻击
10.3.1 描述
主要就是进行抓包重放(如:重放产品购买、订单创造等)测试。
10.3.2 测试步骤
人工测试。
10.3.3 威胁等级
根据重放业务进行判定危险等级。
10.2.4 安全建议
根据业务具体情境提供不同的安全建议。
10.4 用户枚举
10.4.1 描述
尝试爆破枚举用户。
10.4.2 测试步骤
手工测试。
此类漏洞情境一般是:登录界面无验证码、有明显的返回信息(如:该账号不存在、密码错误等)。
10.4.3 威胁等级
要看公司的规模、用户名的形式(如:*号码)等来判定危险等级。
10.4.4 安全建议
一般的安全建议是设置严格的登录信息验证,如验证码、手机验证码等。
10.5 暴力破解
10.5.1 描述
主要是测试业务中查询、登录等功能,尝试使用暴力枚举的方式进行破解。
10.5.2 测试步骤
手工测试。
10.5.3 威胁等级
根据暴力破解的业务和结果进行判定(如:若成功爆破出用户账号和密码,风险等级为高)。
10.5.4 安全建议
一般的安全建议是设置严格的信息验证,如验证码、手机验证码等。
10.6 注入/XSS/CSRF
10.6.1 描述
和WEB测试类似,主要测试站点存在的常见的WEB漏洞。
10.6.2 测试步骤
可手工测试也可以使用工具扫描、测试。
10.6.3 威胁等级
此类漏洞一般为高,具体的可以看存在漏洞的业务进行判定。
10.6.4 安全建议
参考WEB漏洞的安全建议。
第十一章 附录
测试工具清单吞龙
MobSF signapk jd-gui-windows dex2jar apktool adb AndroidKiller 改之理 drozer Burpsuite GameGuardian ApkIDE少月版V3.5.0 GDA3.33 IDA Pro Reflector
APP应用安全测评表
安卓安全思维导图
APK攻防思维导图
*本文作者:吞龙,转载请注明来自FreeBuf.COM