综合实战:完整App安全测试流程——从扫描到渗透到报告
说实话,做了这么多年移动安全,我最怕听到的一句话就是:“你帮我测一下这个App安不安全。” 因为安全测试从来不是一键扫描就能搞定的事。它是一套完整的流程,从信息收集、自动化扫描,到手动渗透,最后落到一份能指导修复的报告上。
今天这一章,我就带你走一遍完整的实战流程。咱们拿一个虚构的“企业办公助手”App做靶子,把从零到一的测试过程拆开揉碎了讲。
核心思路:自动化扫描负责“广覆盖”,手动渗透负责“深挖掘”。两者缺一不可。
第一阶段:信息收集与预处理
拿到一个App,我习惯先做三件事:
- 反编译APK:用jadx或GDA打开,看看有没有硬编码的密钥、API地址、第三方SDK。
- 抓包配置:设置Burp Suite或Charles的代理,安装用户证书。注意Android 7以上有证书锁定,得用Xposed或Frida绕过。
- 了解业务逻辑:注册个账号,跑一遍核心功能。比如这个办公App,有登录、审批、文件上传、即时通讯。
嗯,这里有个坑。我曾经遇到一个App,反编译后发现所有API都走的HTTPS,但抓包却全是明文。后来发现是客户端做了双向认证,但服务端没校验——说白了,就是个摆设。所以别光看代码,一定要动手验证。
第二阶段:自动化漏洞扫描
自动化扫描是效率利器。我一般分两层扫:
2.1 静态扫描
用MobSF(Mobile Security Framework)跑一遍。它能自动检测:
- WebView远程代码执行风险
- 不安全的文件存储(比如SharedPreferences存密码)
- Intent劫持风险
- 证书锁定缺失
跑完后,MobSF会生成一份报告。但别全信——它经常报假阳性。比如它说“WebView启用了JavaScript接口”,但实际那个接口只加载了本地HTML,风险很低。这时候就需要人工判断。
2.2 动态扫描
我习惯用Drozer做自动化组件测试。它会枚举所有暴露的Activity、Service、BroadcastReceiver,然后尝试越权调用。
# 枚举所有可导出的Activity
dz> run app.activity.info -a com.example.office
# 尝试直接拉起一个需要登录的Activity
dz> run app.activity.start --component com.example.office com.example.office.ui.AdminPanelActivity
你猜怎么着?这个办公App的AdminPanelActivity居然是可导出的,而且没做权限校验。直接拉起就能看到所有员工的审批记录。这就是典型的“组件暴露”漏洞。
我的经验:自动化扫描能帮你发现80%的“低垂果实”,但剩下20%的严重漏洞,往往藏在业务逻辑里。比如越权访问、支付篡改、密码重置逻辑缺陷——这些自动化工具很难抓到。
第三阶段:手动渗透测试
手动渗透才是真正考验功力的地方。我一般按这个顺序来:
3.1 认证与会话管理
先测登录。这个App用的是JWT做身份认证。我截获了Token后,尝试:
- 修改alg为none(经典攻击,但大部分服务端已经防了)
- 修改sub字段为其他用户ID
- 重放旧Token(看有没有过期机制)
结果发现,把Token里的userId改成1001,就能直接以管理员身份登录。这就是“越权访问”——服务端只信任客户端传来的用户标识,没做二次校验。
3.2 数据存储安全
检查App的本地存储。用adb连上设备,进到/data/data/com.example.office/目录:
adb shell
run-as com.example.office
cat databases/office.db
好家伙,数据库里明文存了用户的手机号和通讯录。更离谱的是,SharedPreferences里有个isProUser=true的键值对。改成false?不,改成true就能解锁付费功能。这就是典型的“客户端信任”问题。
3.3 网络通信安全
抓包看API请求。我发现文件上传接口是HTTP的,而且没做任何校验。直接上传一个包含恶意代码的HTML文件,然后通过另一个接口访问它——XSS攻击就这么成了。
为什么会这样?因为开发只关注了主业务的HTTPS,忽略了文件存储域名的安全配置。说白了,就是“木桶效应”——最短的那块板决定了整体安全水位。
3.4 业务逻辑漏洞
这个最考验脑洞。我测试了审批流程:
- 提交一个审批请求,金额1000元
- 抓包修改金额为-1000元
- 服务端没校验负数,直接扣了别人的额度
这就是“整数溢出/负数绕过”。开发只做了前端校验,后端完全信任。我见过不少App,前端校验做得花里胡哨,后端却形同虚设。
注意:手动渗透时一定要控制风险。别在生产环境搞破坏,也别修改别人的真实数据。我一般用测试账号,在测试环境操作。如果必须用生产环境,只做只读测试,比如信息泄露验证,绝不写数据。
第四阶段:漏洞报告与修复建议
测试完了,最后一步是写报告。一份好的安全报告,应该让开发看得懂、修得了、排得了优先级。
我习惯用这个模板:
| 漏洞编号 | 漏洞名称 | 风险等级 | 影响范围 | 修复建议 |
|---|---|---|---|---|
| VULN-001 | JWT越权访问 | 严重 | 所有用户数据 | 服务端校验Token中的userId与当前会话是否一致 |
| VULN-002 | 本地数据库明文存储 | 高危 | 用户隐私数据 | 使用Android Keystore加密敏感字段 |
| VULN-003 | 文件上传XSS | 中危 | 文件存储域名 | 上传文件做Content-Type校验,存储域名启用HTTPS |
| VULN-004 | 负数金额绕过 | 高危 | 财务系统 | 后端校验金额必须大于0 |
每个漏洞我还会附上:
- 复现步骤(截图+请求报文)
- 影响分析(比如“攻击者可查看任意员工工资”)
- 修复代码示例(如果可能)
一个小技巧:报告里别只写“修复建议:加强校验”。要写具体,比如“在UserController.java第45行,增加userId与sessionId的比对逻辑”。开发拿到报告就能直接改,不用再问“你说的加强校验是改哪里?”
知识体系总览
下面这张图,是我自己总结的完整测试流程。每次做项目前,我都会对着它过一遍,确保没有遗漏。
写在最后
这一套流程走下来,你会发现安全测试其实是个“体力活+脑力活”的结合。自动化工具帮你省时间,但真正决定漏洞发现深度的,还是你对业务逻辑的理解和对细节的敏感度。
我记得刚入行时,总觉得手动渗透很酷,恨不得每个接口都测一遍越权。后来发现,真正高效的测试是“带着问题去测”——先想清楚这个App最值钱的数据是什么,攻击者最可能从哪里下手,然后集中火力打那几个点。
嗯,今天就聊到这儿。希望这套流程能帮你建立起自己的测试框架。下次拿到一个App,别急着扫,先花10分钟想清楚:我要测什么?从哪里开始?报告写给谁看?想清楚了,效率翻倍。