编写进度
Table of Contents
- Android App安全基础
- 程序代码安全测试 - APP文件、程序进程
- 服务交互安全测试 - 程序进程、前段界面、接口端口
- 鉴权认证安全测试 - 接口端口、内存数据、网络通信
- 本地数据安全测试 - 内存数据、本地存储
- 网络传输安全测试 - 网络通信
- App加固技术
Android App安全基础
Android APP生成过程
graph LR
    java[.java文件] -->|javac|cls[.class文件]
    cls[.class文件] --> dx[dx]
    jar[.jar文件] --> dx[dx]
    dx[dx] --> dex[class.dex]
    dex[class.dex] -->|dex2oat| oat[oat格式的class.dex文件]
    dex[class.dex] -->aapt[aapt]
    resource[resource] -->aapt[aapt]
    aapt --> .apk文件
    .apk文件 --> jarsigner 
    jarsigner--> zipalign
    zipalign --> signsign[signed .apk文件]-  通过javac将java源代码生成字节码.class文件
- 通过dx –dex –output=class.dex Test.class将.class文件和jar包生成Android App可执行文件class.dex
 oat格式文件是android系统自带的ELF文件格式,包括classes.dex文件内容,及classes.dex文件转换的机器指令,存储在/data/dalbik-cache/arm/data@App@com.demo.test-1@test.apk@classes.dex
-  通过aapt将.dex文件和其他音视频资源文件打包成.apk文件
- 通过jarsigner对生成的apk文件进行数字签名,防止APP被篡改
- 通过zipalign使apk文件压缩部分在字节边界上使对齐
安全测试工具
静态分析工具 - 测试App是否存在防反编译和防篡改的问题
- apktool 检测防篡改能力 - 反编译 - java -jar apktool.jar d -f Test.apk
- 重打包 - java -jar apktool.jar b -f directory_name -o Test.apk java -jar signapk.jar testkey.x509.pem testkey.pk8 old.apk new.apk
 
- baksmali 作用 classes.dex -反编译-> smali - java -jar baksmali.jar classes.dex -o smalifile
- smail 作用 smali –> classes.dex - java -jar smali.jar smalifile -o classes.dex
- dex2jar 作用 dex –> jar - sh d2j-dex2jar.sh -f ~/path/to/apk_to_decompile.apk
- [ ] jd-gui 作用 展示jar包中源码 
- [ ] jeb 用于逆向工程/审计apk文件的反编译工具 
动态分析工具 - 测试防调试、防注入、防内存转储、漏洞测试等问题
- [ ] DDMS(Dalvik debug monitor service)是安卓开发环境中的Dalvik虚拟机调试监控服务
- [ ] gdb(GNU project debugger)是LInux系统的GCC调试工具
- [ ] IDA Pro 逆向神器 脱壳
- [ ] Drozer是一个进行综合安全评估的Android安全测试框架
数据包分析工具- 测试数据通信时存在明文传输、数据弱加密、中间人攻击漏洞
- [ ] Burpsuite/Fiddler
- [ ] Wireshark
挂钩工具 - 解决加密时上述工具无法使用的问题
- [ ] Xposed框架1 在不修改APK文件的情况下控制程序运行
- [ ] Frida 开源的跨平台挂钩框架,用来脱壳关键的函数,达到内存转储的目的
- [ ] inject App进程注入评测工具
App相关的信息资产
程序代码安全测试 - APP文件、程序进程
运行环境测试4
防反编译测试5
反编译工具检测
- 检测目的 - 检测App是否可以防止反编译工具,是否具有防逆向保护措施 
- 检测方法 - 通过反编译工具对apk文件进行反编译,查看是否具有防逆向保护措施
- 通过IDA Pro等反汇编工具对动态库so文件进行反汇编,查看App是否具有防反汇编的能力
 
- 检测结论 - 若App的dex文件和so文件无法正常反编译或者App经过加固处理,则通过测试 
- 修复建议 - 对App文件结构进行变形或加密,让反编译工具无法识别,或对App文件进行加固处理 
代码混淆检测
- 检测目的 - 检测App反编译后的源码是否经过混淆处理 
- 检测方法 - 通过反编译工具对apk文件进行反编译,查看代码中的类、字段和方法是否经过混淆处理 
- 检测结论 - 若反编译后源码中的类、字段和方法使用a、b、c、d等无意义的字符重命名,则通过测试 
- 修复建议 - 对App源码进行混淆处理 
混淆强度检测
- 检测目的 - 检测App反编译后的源码的混淆强度,查看是否能够有效地保护代码安全 
- 检测方法 - 检测dex文件代码中所有的类名、函数名、字段、方法,是否都经过混淆处理,例如反编译后无法正常识别Java层函数的功能
- 检测so文件中所有类名、函数名、字段、方法,是否都经过混淆处理,例如反汇编后无法正常识别Native层函数功能
 
- 检测结论 - 若反编译后代码*不能识别*出App函数的功能,则通过测试 
- 修复建议 - 针对dex文件和so文件的类名、函数名、字段、方法进行高强度混淆 
关键代码(敏感逻辑和数据保护)检测
- 检测目的 - 检测App是否对关键代码和数据实施有效的保护措施,是否暴露业务逻辑 
- 检测方法 - 通过反编译工具对apk文件进行反编译,结合manifest.xml配置文件,分析App注册、登陆、支付过程、加密算法、数据通信等关键功能代码,查看相关代码逻辑是否有明显的暴露 
- 检测结论 - 若App关键业务代码(如相关业务字符串)未暴露,且关键数据经过加密和隐藏保护处理,则通过测试 
- 修复建议 - 将App关键代码进行隐藏、混淆、加壳等处理,从而无法逆向出重要的代码信息 
防篡改测试6
程序文件防篡改检测
- 检测目的 - 检测App启动时是否进行了完整性校验,是否对客户端代码、资源文件进行修改,是否具有防篡改机制 
- 检测方法 - 使用反编译工具Apktool对目标文件进行反编译
 java -jar apktool.jar d -f /path/to/test.apk
- 修改相关代码,篡改AndroidManifest.xml、assets文件、res文件等
- 使用apktool重新打包签名后再运行App查看运行结果
 java -jar apktool b -f /path/to/test
 
- 使用反编译工具Apktool对目标文件进行反编译
- 检测结论 - 若打包后安装后*不能正常运行*,则通过测试 
- 修复建议 - 采用完整性校验技术对安装包进行校验,校验对象包括原包中代码、资源文件、配置文件等所有文件,一旦校验失败,立即退出 
防调试测试7
TODO 调试工具防护检测
- 检测目的 
- 检测方法 
- 检测结论 
- 修复建议 
TODO 调试行为防护检测
- 检测目的 
- 检测方法 
- 检测结论 
- 修复建议 
内存防护检测
- 检测目的 - 检测App内存是否具有内存防护功能,防止内存转储 
- 检测方法 - 运行App,使用ps命令查看进程PID
-  使用 gdb -p <PID>挂载App进程后,使用(gdb) gcore转储内存
 
- 检测结论 - 若未生成corefile - core.<pid>,则通过测试
- 修复建议 - 通过监控 - /proc/pid/mem和- /proc/pid/pagemep来防止内存转储
防注入测试8
进程防护检测
- 检测目的 - 检测App进程空间是否可以被注入第三方动态so文件 
- 检测方法 - 运行App,通过注入工具或脚本,将第三方动态库文件注入App进程空间,查看第三方动态库是否在进程的内存空间中
 
- 检测结论 - 若第三方动态库文件*不能注入*到目标进程空间,则通过测试 
- 修复建议 - 增加ptrace函数的检测功能,使第三方无法使用该函数附加进程
- 修改linker中的dlopen函数,防止第三方进行so加载
- 定时检测App加载的第三方so库,若发现使被注入的so库,程序进程立即报异常
 
服务交互安全测试 - 程序进程、前段界面、接口端口
进程间交互
检测目的
检测进程间数据通信是否具有泄露用户信息的风险
检测方法
查看AndroidManifest.xml文件中的
-   <activity android:exported="true"则可以被第三方App启动
-   <provider android:authorities="com.bgy.ssm.fileprovider" android:exported="true"则可以被第三方app调用,实现增、删、改、查
-   <receiver android:exported="true"则可以接收第三方App发送的广播消息
-   <service android:enabled="true" android:exported="true"则可以被第三方app启动
检测结论
客户端App用于跨进程通信的4种组建分别为Activity、ContentProvider、BroadCast、Service
在 未明确要求 的情况下,只要以上配置中存在任一 exported=true 则测试 不通过
修复建议
在未明确要求的情况下,在AndroidManifest.xml配置文件中设置该组建的exported属性为false,或对组建进行权限
屏幕交互
界面劫持检测
- 检测目的 - App是否具有防界面劫持(UI欺骗)功能,防止黑客伪造界面对原有界面进行覆盖,窃取用户和密码等敏感信息 
- 检测方法 - 反编译源码,查看是否具有检测程序进入后台运行的代码, 当程序不是因为触摸返回键和HOME键今后后台运行时,提醒用户具有被劫持的风险 - @Override public boolean onKeyDown(int keyCode, KeyEvent event){ // 判断程序进入后台运行是否未触摸返回键和HOME键造成的 if((keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_HOME) && event.getRepeatCount()==0){ flag = false; } return super.onKeyDown(keyCode, event); } @Override protected void onPause(){ // 程序进入后台如果不是触摸返回键和HOME键造成的,则进行劫持风险提示 if(flag){ // 弹出警示信息 Toast.makeText(getApplicationContext(), "程序已经进入后台运行,具有劫持的风险", Toast.LENGTH_SHORT).show(); } super.onPause(); }
- 编写透明界面,当运行至登陆、支付等界面时进行覆盖,查看是否具有风险提示 
 
- 修复建议 - 对App的UI界面进行校验,强制将自身UI时刻设置成顶层显示,其中HOME键除外,或自身UI界面进入后台运行后弹框提示用户App已经进入后台运行,有界面劫持风险 
防截/录屏检测
- 检测目的 - 检测App运行后是否存在防截/录屏保护措施 
- 检测方法 -  通过 screencap命令进行连续截屏,查看界面后的图片是否显示敏感信息
-  通过 screenrecord命令进行录屏,查看录制后的视频是否显示敏感信息
 
-  通过 
- 修复建议 - App要实现防截录屏的保护措施 
WebView交互
克隆攻击检测
- 检测目的 - 检测App中是否存在设置为可被导出的Activity组件,且组建中包含WebView调用,存在导致敏感信息泄露的风险 
- 检测方法 -  通过JEB攻击反编译dex文件的源码,查看客户端是否使用了WebView空间,并将 setAllowFileAccessFromeFileURLs或setAllowUninvertedFileAccessFromFileURLsAPI设置为true
- 检测file域的路径是否做了严格限制
 
-  通过JEB攻击反编译dex文件的源码,查看客户端是否使用了WebView空间,并将 
- 检测结论 - 若App使用WebView组建,并将 - setAllowFileAccessFromeFileURLs或- setAllowUninvertedFileAccessFromFileURLsAPI设置为- false,则通过测试
 若App使用WebView组建,并将- setAllowFileAccessFromeFileURLs或- setAllowUninvertedFileAccessFromFileURLsAPI设置为- true,且file域的路径做了严格限制,则通过测试
- 修复建议 - 严格限制包含WebView调用的Activity组建的导出权限,关闭导出权限或限制导出组建的发起者 
WebView安全检测
- 检测目的 - 检测App使用的WebView空间加载的外部资源是否存在潜在风险 
- 检测方法 - 检测App源码,查看客户端是否对WebView对空间加载的资源文件进行了校验,过滤风险代码 
- 检测结论 - App使用WebView空间减灾的HTML未明确要求使用Javascript, 
 未对加载文件进行校验,或未使用安全的通信协议,
 并在WebView加载的程序中有实现发送短信,拨打电话等敏感行为的操作代码,则本项测试不通过
- 修复建议 - WebView加载的HTML页面,在未明确要求的情况下,禁用Javascript
- 对WebView加载的外部文件进行校验
- 采用HTTPS安全通信协议,不要在WebView加载的外部文件中实现敏感操作的代码
 
接口端口交互
对象反序列化检测
- 检测目的 - 检测App是否使用安全的API实现序列化和反序列化,是否存在反序列化漏洞 
- 检测方法 - 通过JEB工具反编译dex文件的源码,查看客户端App是否具有实现序列化和反序列化的源代码
- 检测实现序列化和反序列化的API是否具有潜在风险和漏洞
 
- 检测结论 - 若客户端App不具有序列化和反序列化的代码,或实现序列化和反序列化的API不具有潜在风险和漏洞,则通过测试 
- 修复建议 - App采用安全框架的API实现序列化和反序列化 
Wormhole漏洞检测
- 检测目的 - 检测App是否存在Wormhole漏洞 
- 检测方法 - 检测App是否私自开启HTTP服务,是否进行身份认证
- 通过nmap工具扫描,检测App代码中是否开放某个TCP端口
 
- 检测结论 - 如App私自开启了HTTP服务,开放某个TCP端口,同时该服务无身份认证,则本测试 不通过 
- 修复建议 - App关闭HTTP服务和端口,增加App的访问权限控制机制 
鉴权认证安全测试 - 接口端口、内存数据、网络通信
注册过程测试
注册信息保护检测
- 检测目的 - 检测App注册密码的复杂度(密码内容要求字母大小写、数字、特殊字符组合,长度等)和注册信息在本地存储时的保护程度是否足够高 
- 检测方法 - 检测App注册密码的复杂度 - public static boolean isPasswordChecked(CharSequence data){ return Pattern.compile("^((a-z0-9A-Z)+[_]?){6,20}$").matcher(data).find(); }
- 检测App在本地存储的注册信息是否加密存储,加密密钥是否进行了隐藏处理 
 
- 检测结论 - 如果对注册密码复杂度、长度进行了限制处理,且对本地存储的注册信息进行了加密保护,加密密钥隐藏,则通过测试 
- 修复建议 - 对注册密码的复杂度和长度进行限制
- 对在本地存在的用户注册信息进行加密处理,隐藏加密密钥
 
注册信息传输检测
- 检测目的 - 检测App将用户注册信息传输到服务器端的过程中是进行了加密保护 
- 检测方法 - 使用Burpsuite拦截App注册用户的数据包,查看数据包是否加密 
- 检测结论 - 若App在将用户注册信息传输到服务器端时进行了加密处理,则通过测试 
- 修复建议 - 在将用户注册信息传输到服务器端的过程中,对用户注册信息进行加密处理 
注册过程防爆破检测
- 检测目的 - 检测App在注册账户时,是否可以爆破获取正确的验证码,注册任意用户 
- 检测方法 - 在注册界面填写完注册信息后,点击“获取验证码”,使用抓包工具对其抓包,对数据包中的验证码进行暴力破解,爆破成功后,便可注册任意账号 
- 检测结论 - 若在注册App时验证码被爆破,可以任意注册账户,则本项测试不通过 
- 修复建议 - 使用复杂的验证码,验证码长度不低于6位,包含数字及字母
- 对发送验证码请求进行时间和次数限制
- 验证码在传输时进行有效的加密处理
 
注册过程防嗅探检测
- 检测目的 - 检测在App注册过程中是否可以利用已有社工库中的手机号、邮箱、用户名、密码等信息,通过撞库方式频繁嗅探注册账户 
- 检测方法 - 利用Burpsuite拦截注册用户时的数据包,分析查看是否暴露账户、密码参数,然后利用社工库数据替换账户、密码参数,进行撞库,从而获取用户注册 
- 检测结论 - 若在注册时暴露账户、密码参数,具有利用撞库对用户注册信息进行嗅探的风险,则本项测试不通过 
- 修复建议 - 对传输的注册账户、密码等敏感信息进行强加密处理
- 服务器端限制访问次数
 
登陆过程测试
密码安全验证检测
- 检测目的 - 检测App登陆密码的验证方案是在本地验证还是在服务器端验证,验证过程中是否加入了设备信息 
- 检测方法 - 利用JEB逆向分析App登陆功能的源码,分析密码验证中是否加密了设备信息IMEI 
- 检测结论 - 若密码验证在服务器端进行,且加入了设备信息,避免在非法设备登陆,则通过测试 
- 修复建议 - App登陆密码在服务器端进行验证,并加入设备信息,以降低用户登陆密码泄露的风险 
登陆信息加密传输检测
- 检测目的 - 检测App在将用户登录信息传输到服务器端的过程中是否进行了加密保护,以免被攻击者拦截网络流量,窃取用户登陆信息 
- 检测方法 - 使用Burpsuite拦截app登陆操作的数据包,分析是否明文传输用户信息 
- 检测结论 - 若App在将用户注册信息传输到服务器端时进行了加密处理,则通过测试 
- 修复建议 - App在将用户登陆信息传输到服务器端的过程中,要对用户登陆信息进行加密处理 
登陆过程防爆破检测
- 检测目的 - 检测App在登录时,是否可以抓取数据包,利用数据包中的验证码字段/密码字段进行暴力破解 
- 检测方法 - 检测App在登陆时,是否可以爆破验证码/密码,获取正确的验证码和登陆密码 
- 检测结论 - 若App在登陆时验证码和登陆密码可以被爆破,则本项测试不通过 
- 修复建议 - 使用复杂的验证码和登陆密码
- 对发送验证码的请求进行时间和次数限制
- 对验证码、登陆密码进行输入错误次数限制
- 验证码、登录密码在传输时进行有效的加密处理
 
登陆过程防嗅探检测
- 检测目的 - 检测App是否可以通过爆破验证码实现任意账户登陆、任意重置用户密码等操作 
- 检测方法 - 验证码爆破检测
 在登陆界面填写完手机号等信息后点击“获取验证码”,使用抓包工具对其抓包,对数据中的验证码进行暴力破解,爆破成功后便可实现登陆任意账户、任意重置用户密码
- 短信轰炸检测
 在登陆界面填写完手机号等信息后点击“获取验证码”,若短信验证码无获取时间、获取次数限制,便可重放发送短信验证码数据进行短信轰炸
- 探测是否具有撞库风险
 利用工具拦截用户登陆时的数据包,分析查看是否暴露账户、密码参数,然后利用社工库数据替换账户、密码参数进行撞库,从而获取用户登陆信息
 
- 验证码爆破检测
- 检测结论 - 若App通过爆破验证码实现登陆任意账户、任意重置用户密码、短信炸弹,或通过撞库获取用户登陆信息,则此项测试 不通过 
- 修复建议 - 使用复杂验证码、登陆密码
- 对发送验证码的请求进行时间和次数限制
- 对验证码输入错误次数进行限制
- 验证码在传输时进行有效的加密处理
- 服务端限制访问次数
 
登陆过程防绕过检测
- 检测目的 - 检测App是否可以绕过验证码登陆任意账户、修改用户ID获取其他用户信息 
- 检测方法 - 抓取登陆成功后的响应包,之后退出,在登陆其他用户账户时,用登陆成功的响应包替换登陆失败的数据包,检测是否可以绕过验证码、密码验证,进而成功登陆其他用户的账户
- 修改用户ID,检测是否可以获取任意用户信息,若用户身份认证采用单一ID值判断,攻击者可以修改数据包中的用户ID进行重放,从而获取其他用户信息
 
- 检测结论 - 若App可以绕过验证码登陆其他用户,或可以修改用户ID获取其他用户信息,则本项测试 不通过 
- 修复建议 - 加强身份验证机制,使用Token或Session机制,设置访问控制策略,敏感数据采用高强度加密传输 
加强认证检测
- 检测目的 - 检测App客户端是否具有双因子认证机制,保护用户登陆信息 
- 检测方法 - 检测App在登陆时,是否具有双因子认证机制(密码+令牌/指纹/设备信息/短信)
- 使用用户登陆信息在新设备登陆时,查看是否具有短信提醒
 
- 检测结论 - 如Apple具有双因子认证机制和不同设备登录时的短信提醒认证机制,则通过测试 
- 修复建议 - App采用双因子认证机制和不同设备登陆短信提醒认证机制,保护用户登陆信息安全 
会话过程测试
有状态会话标志检测
- 检测目的 - 检测客户端与服务器端交互的会话,是否存在复杂的会话ID,同时服务器是否对其进行校验 
- 检测方法 - 模拟客户端与服务器端登陆,查看是否采用 简单的Sessionid方式标识 客户端
- 利用服务端返回的 _Sessionid构建新的URL 访问服务器端,查看是否能够绕过验证
- 查看客户端与服务器交互时是否采用 *复杂的Key*,是否存在时间有效性校验,防止被伪造
 
- 检测结论 - 若客户端与服务器端会话时采用来复杂加密的Key,同时服务器端对客户端发送的Key进行了校验,攻击这无法伪造,服务器端无响应,则通过测试 
- 修复建议 - 客户端与服务器端通信会话时采用复杂的算法对随机的Sessionid进行加密,同时服务器端对随机的Sessionid进行校验 
无状态会话Token检测
- 检测目的 - 在客户端与服务器端通信会话过程中,检测是否存在Token机制,是否容易被攻击者截取利用 
- 检测方法 - 检测客户端与服务器端通信会话的URL中是否使用携带Token,Token是否明文显示
- 检测客户端与服务器端认证的复杂性,是否采用类似 UID+Toekn+timestamp+密钥 的Toekn机制,并尝试破解
 
- 检测结论 - 若客户端与服务器端通信会话的Toekn能被轻易获取利用或被破解,则本项测试不通过 
- 修复建议 - 每次登陆时重新生成Token,并设置有效期,每次操作后更新Token的时间戳,保证Token有效期往后延续
- 为了避免Token被截获,伪造非法请求,在每次请求时,建议采用 UID+Token+timestamp+密钥+请求参数签名 ,服务器同时验证Token和签名,以保证请求的安全性
 
会话不活跃检测
- 检测目的 - 若客户端与服务器端通信临时终端或长时间不活跃,检测服务器是否立即终止会话 
- 检测方法 - 在客户单与服务器端通信过程中,若长时间不操作,然后再操作时,查看客户端与服务器端是否已中断
- 在客户单与服务器端通信过程中,若临时中断,例如打开微信等其他操作,让服务在后台运行,查看客户端与服务器端是否已中断
 
- 检测结论 - 若客户端与服务器端通信临时中断或长时间不活跃时,服务器端立即与客户端中断会话,需要重新认证,则本项测试结果为通过 
- 修复建议 - 在客户端与服务器端通信会话过程中,增加时间的有效性,例如设置时间为5min,若客户端与服务器长时间不活跃或者客户端服务在后台运行,服务器立即中断本次会话 
加强认证检测
- 检测目的 - 在客户端与服务器端进行敏感交易时,检测服务器端是否存在双因子身份认证机制 
- 检测方法 - 检测客户端与服务器端进行支付、转账等敏感交易时,客户端是否需要多个身份认证方式,同时服务器端是否对其双因子进行校验
- 检测客户端与服务器端进行身份认证过程中,数据是否进行加密处理,加密强度如何
 
- 检测结论 - 若客户端与服务器端存在双因子身份认证,则通过测试 
- 修复建议 - App中涉及敏感用户信息的界面,要求使用双因子身份认证机制,例如采用支付密码和用户预留短信验证码等认证方式 
登出过程测试
会话终止检测
- 检测目的 - 在用户执行登出操作后,检测服务器端是否立即终止与客户端之间的会话连接 
- 检测方法 - 登陆App,执行一些需要在App进行身份验证的操作,并拦截
- 退出App
- 重放步骤1中的操作,显示错误消息或重定向到登录页面
 
- 检测结论 - 若在客户端用户执行登出操作后,服务器立即终止与客户端之间的会话连接,需要用户重新进行登陆认证 
- 修复建议 - 在用户执行登出操作后,立即终止客户端与服务器端的会话连接 
残留数据检测
- 检测目的 - 当用户执行登出操作后,检测服务器是否及时删除客户端对应的Token或Sessionid 
- 检测方法 - 操作客户端登出功能,通过用户名、密码、及之前的Token值或Sessionid值能够登陆成功,则本项测试不通过 
- 检测结论 - 在用户执行登出操作后,若客户端使用之前的Token或Sessionid值能够登陆成功,则本项测试不通过 
- 修复建议 - 当用户执行登出操作后,服务端及时删除户端对应的Token或Sessionid值 
注销过程测试
重新注册检测
- 检测目的 - 检测在客户端注销后,使用相同账户能否重新注册 
- 检测方法 - 检测客户端是否存在注销功能
- 在客户单注销之后,使用相同账户注册,查看是否可以重新注册,测试第三方关联的账户是否也已经注销,还能否正常登陆
 
- 检测结论 - 若注销账户后仍可以使用相同的账户注册,关联的第三方数据无法使用,则通过测试 
- 修复建议 - 在客户端注销操作后,可以使用相同账户重新注册,确认原来的账户信息已经清除 
数据清除检测
- 检测目的 - 检测在App卸载后,本地存储的数据或账户缓存等信息是否全部清除 
- 检测方法 - 安装App,先注册,登录试用,然后卸载,查看本地注册的用户账户信息等数据是否及时删除
- 重新安装App,查看使用之前的账户和密码是否可以直接登陆
 
- 检测结论 - 若卸载App后,本地数据完全及时清除,则通过测试 
- 修复建议 - 在App卸载后,及时删除本地存储的全部数据 
本地数据安全测试 - 内存数据、本地存储
数据创建测试
用户协议检测
- 检测目的 - 检测App是否存在用户协议声明。若存在,是否对使用用户信息用户及保护措施进行声明,是否存在违规行为 
- 检测方法 - 安装运行App,试用App的所有主要功能,并抓包,通过数据包和源代码了解其行为特征
- 查看是否存在用户协议,以及协议内容是否声明App需要手机的用户信息及保护措施
 
- 检测结论 - 若App存在用户服务协议,且声明了用户信息用途及保护措施,则通过测试 
- 修复建议 - App手机用户个人信息前,必须在用户服务协议中声明,需要收集用户设备的哪些信息、具体用途、及保护用户信息的安全措施和具体承诺 
数据采集检测
- 检测目的 - 检测App是否过度申请系统敏感权限,使用该权限时是否提示用户授权,是否过度手机用户数据,数据传输过程是否安全 
- 检测方法 -  查看AndroidManifest.xml文件标签,分析App所申请的系统权限,是否存在过度申请的敏感权限 
- 查看App调用系统的敏感权限时是否提示用户授权
- 分析App源码及数据包内容,查看是否过度收集在用户协议声明范围外的用户数据,确认数据传输过程中的安全性
 
-  查看AndroidManifest.xml文件
- 检测结论 - 若App无过度申请系统敏感权限,且在使用该权限时提示用户授权,同时没有过度收集用户数据,则通过测试 
- 修复建议 - App发布时需要删除不需要的系统敏感权限,在申请系统敏感权限时,需要提示用户授权,不得私自上传在协议中未声明的用户信息 
数据输入检测
- 检测目的 - 检测App是否实现了自带的安全键盘,且启动键盘时数字是否随机分布,关键的输入框是否禁用复制粘贴功能,是否存在验证码校验机制,验证码是否安全 
- 检测方法 - 检测App是否实现了自定义软键盘,在每次启动时按键数字随机分布,且按键时不存在按键阴影,按键回显等特效
- 检测要求输入敏感数据(登陆密码、支付密码、银行卡账户等)输入框禁用复制粘贴功能
- 检测验证码是否由图形验证码或短信验证码组成,是否通过服务器端返回给客户端
 
- 检测结论 - 若App实现了自定义软键盘,键盘数字实现了随机分布,具有安全的验证码,同时密码输入框禁用了复制粘贴功能,则通过测试 
- 修复建议 - App客户端实现自定义的软键盘,软键盘每次启动时都要随机分布,且按键无回显、阴影等特效
-   要求输入登陆、支付密码、银行卡账户等输入框禁用复制粘贴功能 设置 android:longClickable="false"关闭其功能
- 增加复杂图形验证码或短信验证码,且在传输过程中对数据进行加密
 
数据生成检测
- 检测目的 - 检测App生成数据的存储形式时是结构话还是非结构话,数据是否经过加密后存储 
- 检测方法 - 检测App生成的结构化数据,要求数据内容加密后存储
- 检测App生成的非结构化数据,要求数据内容加密后存储
 
- 检测结论 - 若本地存储的数据经过加密处理,则通过测试 
- 修复建议 - 不管生成的数据是采用结构化还是非结构化形式存储,都要求加密后存储 
数据存储测试
访问控制检测
- 检测目的 - 检测App是否具备完善的权限管理机制,是否能够与其他App隔离,是否在权限允许的范围之外存在数据被其他客户端访问的风险 
- 检测方法 - 查看App本地存储文件的权限 - ls -al files # 本地存储file文件权限 ls -al shared_pref # 本地存储xml文件权限 ls -al app_webview # 本地存储的cache文件权限 ls -al databases # 本地存储的db文件权限
- 检测结论 - 如客户端具备完善的权限管理机制,以最小权限为原则,则通过测试 
- 修复建议 - App客户端严格控制本地生成敏感数据访问权限,避免被第三方App非法访问导致用户信息泄露 
数据加密检测
- 检测目的 - 检测App在本地存储的用户信息是否经过了加密处理,加密密钥是否进行了保护,加密算法是否合理,生成的随机数强度是否较高,避免造成用户信息泄露风险 
- 检测方法 - 检测App在本地生成的数据文件是否加密,检测App在本地存储的文件是否加密 
- 检测结论 - 若本地数据进行了加密处理,加密密钥进行了保护处理,且采用多种加密算法组合加密,对不同的数据采用了不同的加密算法,采用安全的方式生成随机数,则通过测试 
- 修复建议 - 对App在本地存储的用户信息进行加密处理
- 对对称加密算法的加密密钥进行加密保护和隐藏处理
- 对APp在本地存储的用户信息进行多重加密,并对用户数据采用多种加密方式
- 避免使用不安全的随机数生成类
- 避免使用不安全的加密算法
 
数据处理测试
程序日志检测
- 检测目的 - 检测App源码中的调试信息是否关闭,在调试信息中是否写入敏感信息 
- 检测方法 - 反编译源码,查看是否存在日志调试代码,要求不得存在日志调试代码 - private void save(){ String mName=etUsername.getText().toString(); String mPwd=etPwd.getText().toString(); mEditor.putString("Name",mName); mEditor.putString("Pwd",mPwd); mEditor.commit(); Log.d("TEST","本地存储"+"用户名"+mName+"密码"+mPwd); }
- 动态运行App客户端,使用 - logcat查看后台打印日志是否存在用户敏感数据,要求后台不得打印日志调试信息
 
- 检测结论 - 若App关闭了源码中的调试信息,则通过测试 
- 修复建议 - App发布时应删除源码中的日志调试代码 
敏感数据不当使用检测
- 检测目的 - 检测App源码和行为特征是否符合App安全相关标准的规定 
- 检测方法 - 反编译App代码,查看是否私自手机用户敏感信息,抓包拦截,检测是App是否私自上传用户隐私到服务器 
- 检测结论 - 逆向分析源码和数据包,若符合App安全相关标准的规定,则通过测试 
- 修复建议 - App源码要进行严格审核处理,禁止在用户未知情的情况下私自收集用户信息 
数据共享测试
第三方SDK用户协议检测
- 检测目的 - 检测在App服务协议中是否声明第三方SDK收集用户信息的用途,是否过度收集用户个人信息 
- 检测方法 - 查看用户协议内容是否声明共享用户信息给第三方SDK,并通过抓包查看第三方SDK的行为特征 
- 检测结论 - 若用户协议中明确声明App信息与第三方共享情况,则通过测试 
- 修复建议 - App要明确声明是否会与第三方共享用户信息,以及共享用户信息的具体用途 
与第三方SDK数据共享检测
- 检测目的 - 检测App是否在用户未知情的情况下,私自共享用户个人信息给第三方SDK,以及第三方SDK是否私自收集用户个人信息到指定服务器 
- 检测方法 - 分析App源码和数据包,查看是否在用户未知情的情况下,将收集的用户信息私自上传至第三方服务器
- 分析App嵌入的第三方SDK源码和数据包,查看是否存在第三方SDK在用户不知情的情况下,将收集的用户信息私自上传至第三方服务器
 
- 检测结论 - 若分析源码内容和数据包后,符合App安全相关标准的规定,则通过测试 
- 修复建议 - 在App共享数据给第三方SDK的服务协议之外,禁止App和第三方SDK私自采用短信或数据包等形式,收集用户信息并上传到指定服务器 
数据备份测试
敏感数据备份检测
- 检测目的 - 检测App应用数据是否可以备份,是否能够防止攻击者复制App数据 
- 检测方法 - 查看Androidmanifest.xml文件中的allowBackup属性是否为true 
 - <application android:allowBackup="true"
- 检测结论 - 在App不具备备份功能的情况下,若 - <application android:allowBackup="false"则通过测试
- 修复建议 - 在App不具备备份功能的情况下,应将 - <application android:allowBackup="false"
备份数据加密强度检测
- 检测目的 - 检测App备份的数据是否进行加密处理,并且要求使用复杂的加密强度高的算法 
- 检测方法 - 若采用对称算法加密,则判断对称算法的密码是否存储安全,加密算法的源代码是否可以被破解 
- 检测结论 - 若App备份的数据进行了加密处理,则通过测试 
- 修复建议 - 采用多种混合算法加密,例如AES256,MD5,HASH,DES,BASE64 
数据销毁测试
后台运行数据检测
- 检测目的 - 检测App客户端在切入后台运行时是否对收集存储的文件、数据库、配置文件、缓存文件等进行及时清理操作 
- 检测方法 - App切入后台运行时,查看本地生成的db文件、xml文件或者内存中的数据是否进行了删除
- 导出本地的缓存信息文件,查看是否有敏感信息暴露
 
- 检测结论 - 若App在切入后台运行时,本地生成的临时文件db、xml、cache中的数据或者运行时内存中的用户数据做到了及时清理,则通过测试 
- 修复建议 - App在切入后台运行后,应及时清理本地存储的用户敏感信息和内存中的数据信息 
敏感数据清除检测
- 检测目的 - 检测App在退出或被卸载时,是否彻底删除在手机本地存储的文件、数据库、缓存、配置信息等文件 
- 检测方法 - 使用反编译工具apktool对目标文件进行反编译,查看App代码中是否具有清除缓存信息的方法 - removeSessionCookie()/deleteCookie()- if("ClearWebView" , "webView.clearCache"){ try{ CookieSyncManager.createInstance(this.Y.getApplicationContext()); CookieSyncManager.getInstance().removeSessionCookie(); CookieSyncManager.getInstance().sync(); }catch(Exception v0_1){ } }
- 检测结论 - 若本地生成文件仍然存在,则本项测试 不通过 
- 修复建议 - 检测App在退出或被卸载时,应彻底删除在手机本地存储的文件、数据库、缓存、配置信息等信息 
网络传输安全测试 - 网络通信
安全传输层测试
TLS实现检测
- 检测目的 - 检测客户端与服务器端交互核心的通信会话是否采用HTTPS,同时是否为现有最佳实践方式 
- 检测方法 - 使用Burpsuite/Wireshark抓包,判定用户登录、交易等私密连接是否使用HTTPS进行网络通信,查看TLS版本是否高于1.0 
- 检测结论 - 若客户端与服务器端通信采用HTTPS,且TLS版本高于1.0,则通过测试 
- 修复建议 - 客户端与服务器端核心的通信会话均采用HTTPS,同时TLS版本高于1.0 
CA证书检测
- 检测目的 - 检测客户端与服务器建立安全通道时,客户端是否验证远程端点的X.509证书,是否只接受受信任的CA签名证书 
- 检测方法 - 检测CA证书的合法性,是否为受信任的CA签名证书,App是否只接受受信任的CA签名证书 - 抓取App与服务器端交互的数据,校验证书的颁发机构
- 在源码中检查客户端是否只接受受信任的CA签名证书
 
- 检测结论 - 若截获的数据包中证书由可信任机构签发,且在有效期内,且访问服务器与证书绑定的一致,同时只接受信任的CA签名证书,则通过测试 
- 修复建议 - 客户端验证远程端点的X.509证书,只接受受信任的CA签名的证书 
证书校验检测
- 检测目的 - 检测客户端和服务器是否对证书进行双向校验 
- 检测方法 - 反编译App代码,检测是否存在客户端验证服务器端证书的代码- 验证证书内容有效性、数字摘要是否一致
 
- 反编译App代码,检测是否存在客户端发送本地证书给服务器端认证的代码
 
- 反编译App代码,检测是否存在客户端验证服务器端证书的代码
- 检测结论 - 若客户端对服务器端返回的证书进行了验证,同时服务器端也对客户端证书进行了校验,则通过测试 
- 修复建议 - 建议一般的App要实现客户端对服务器端证书的单向验证,对于安全要求比较高的App,要实现客户端与服务器端证书的双向验证 
主机名校验
- 检测目的 - 检测客户端是否对主机名进行校验 
- 检测方法 - 反编译App代码,查找App通信的代码,查看 - setHostnameVerifier()方法接受任意域名还是进行了主机名验证- public static SSLSocketFactory getFixedSocketFactory(){ MySSLSocketFactory v0; try{ v0=new MySSLSocketFactory(MySSLSocketFactory.getKeystore()); //缺陷代码 ((SSLSocketFactory)v0).setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); }catch(Throwable v1){ v1.printStackTrace(); SSLSocketFactory v0_1 = SSLSocketFactory.getSocketFactory(); } return ((SSLSocketFactory)v0); }
- 检测结论 - 若App接受任意域名,则本项测试 不通过 
- 修复建议 - App对主机名进行校验,不能接受任意域名 
数据加密检测
检测目的
检测在客户端与服务器端通信过程中,业务数据是否以明文方式在网络中传输,数据加密的复杂度如何
检测方法
- 对客户端与服务器端通信的登陆、支付、转账等核心功能进行抓包,查看业务数据是否以明文方式在网络中传输
- 检测数据加密方式的复杂度,url编码、Base64编码、AES\DES加密等
检测结论
若客户端与服务器端交互的业务数据经过多个复杂的算法加密,且无法破解,则通过测试
修复建议
客户端与服务器端交互的上行/下行数据要经过多个复杂算法进行加密,同时加密存储对称加密算法密钥
中间人攻击测试
HTTP中间人会话劫持检测
- 检测目的 - 检测客户端与服务器端交互的数据是否可以被任意篡改,导致重放攻击漏洞 
- 检测方法 - 运行测试App,点击登陆,拦截数据包,并进行修改后放行,查看App运行结果是否能够修改成功 
- 检测结论 - 若客户端与服务器端交互的数据经过加密处理,且数据无法修改,则通过测试 
- 修复建议 - 采用高强度的加密算法对交互数据进行加密/或使用HTTPS
- 对客户端请求的数据和服务器端返回的数据进行完整性校验,防止被篡改
 
HTTPS中间人会话劫持检测
- 检测目的 - 检测App在使用HTTPS时,是否存在中间人攻击漏洞 
- 检测方法 - 反编译源码,查看是否校验服务器端是否可信- 查看实现X509TrustManager接口中 - checkServerTrusted()方法实现是否为空- public MySSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException{ this.sslContext = SSLContext.getInstance("TLS"); this.sslContext.init(null,new TrustManager[]{new X509TrustManager(){ public X509Certificate[] getAcceptedIssuers(){ return null; } public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException{ //实现逻辑为空 } public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException{ //实现逻辑为空 } }},null); }
- 反编译源码,查看站点域名与站点证书的域名是否匹配- 查看 - HostnameVerifier()方法中的- verify()函数是否存在域名校验- NetworkUtils.conn=null; 
 NetworkUtils.is =null;
 NetworkUtils.os=null;
 NetowrkUtils.DO_NOT_VERIFY = new HostanmeVerifier(){- public boolean verify(String s, SSLSession sslSession){ return 1; // 不检查站点域名和站点证书的域名 } }
- 查看 - sethostnameverifier()方法是否接受任意域名- public static SSLSocketFactory getFixedSocketFactory(){ MySSLSocketFactory v0; try{ v0=new MySSLSocketFactory(MySSLSocketFactory.getKeystore()); //缺陷代码 ((SSLSocketFactory)v0).setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); }catch(Throwable v1){ v1.printStackTrace(); SSLSocketFactory v0_1 = SSLSocketFactory.getSocketFactory(); } return null; }
 
- 检测结论 - 若客户端不进行服务器端是否可信、不进行域名校验、接受任意域名,对APP数据包进行拦截和篡改,则造成中间人攻击的风险。 
 若客户端对服务器端返回的SSL证书进行强校验,则通过测试
- 修复建议 - 对SSL证书进行签名CA是否合法、证书是否自签名、主机域名是否匹配、证书是否过期等校验。 
App加固技术
- 第一代加固技术: 通过对源码进行 - 压缩: 检测并一处代码中无用的类、字段、方法和特性
- 优化: 对字节码进行优化,移除无用指令
- 混淆: 使用a、b、c、d等无意义字符对类、字段、方法进行重命名
- 预检: 在Java平台上对处理后的代码进行预检,确保加载的class文件时可执行
 
- 第二代加固技术: 对原始App的dex文件加密,并外包一层克,将App的核心代码进行隐藏 
- 第三代加固技术: 对dex文件中所有的类及方法函数内容进行抽取、加密和隐藏,单独加密后存放在apk中的特定文件内 
- 第四代加固技术: DVMP(dex虚拟机保护) 具有自定义虚拟机、指令集和解释器,未保护的代码在系统虚拟机中运行,保护代码在自定义虚拟机运行 
Table of Contents
应用脱壳
安装Frida客户端
- 在Android上安装Frida Server - adb shell getprop ro.build.version.release # 获取Android版本号 adb shell getprop ro.product.cpu.abi # 查看CPU架构,根据架构下载对应的frida-server-14.2.18-android-arm64.xz xz -d frida-server-14.2.18-android-arm64.xz # 解压frida-server adb push frida-server-14.2.18-android-arm64 /data/local/tmp # 传输到/data/local/tmp目录下 adb shell su chmod a+x /data/local/tmp/frida-server-14.2.18-android-arm64 adb forward tcp:27042 tcp:27042 adb forward tcp:27043 tcp:27043 ./frida-server-14.2.18-android-arm64 python dexDump.py com.test.aspiredoctor
- 在macOS上安装Frida Client - pip3 install frida frida-tools
Footnotes
1 替换Android系统/system/bin/appprocess文件
2 如apk文件和dex文件
3 可导致调用系统功能截取屏幕和录像窃取用户信息,界面劫持,对用户进行钓鱼
4 检测客户端程序是否对已经root的android系统、模拟器和逆向框架进行检测
5 检测客户端程序是否进行代码加密、代码混淆和代码加固,是否易被逆向并泄露程序的设计原理和运行流程
6 检测客户程序是否对自身进行校验
7 检测客户端程序是否可被外部程序动态调试并输出敏感信息
8 检测客户端程序是否存在进程保护和内存保护,防止被外部程序动态注入so文件到指定进程、以及任意修改、转储内存代码行为
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 askding@qq.com
 
            