AppScan 遇到登录无法录制的情况¶
一、现象¶
打开 AppScan 的"扫描配置 → 登录管理",选择自动录制,结果通常是这几种:
1. 录制结束,提示"未检测到登录请求"
2. 登录成功,但扫描一开始就退回登录页,所有请求 302
3. 只录到 /login 与 /captcha,后续接口一个没有
4. 录制时有请求,扫描结果里只有登录页,0 个业务 URL
5. 扫描跑完,漏洞列表全是登录页的"会话令牌未更新""缓存"类问题
根因不是 AppScan 不会用,而是登录过程对自动化不友好。
二、先定位是哪一类登录障碍¶
| 障碍 | 特征 | 常用解法 |
|---|---|---|
| 图形/短信验证码 | 登录请求带 captcha、smsCode |
手工登录 + 会话注入;测试环境关验证码 |
| 动态 token(CSRF) | 登录前先 GET 拿 token,POST 时带回 | 多步骤登录 + 正则提取 |
| 前端加密密码 | 请求里 password 是一串 RSA/AES 密文 |
录制浏览器真实请求(HAR),不要用脚本构造 |
| SSO / OAuth2 | 302 跳到 idp,再跳回,带 code | 手工完成 SSO,注入最终会话;或把 idp 加入范围 |
| SPA 前端路由 | 页面无整页刷新,接口由 XHR 触发 | 用内置浏览器手工浏览,或导入 HAR |
| 扫码登录 | 登录态在手机端确认 | 手工扫码后导出 Cookie |
| App 端 | 有 SSL Pinning、mTLS | 先解决抓包,再导入 HAR |
| 双因素 | 登录后还要 OTP | 多步骤登录 + 交互式提示,或测试账号关闭 MFA |
先把障碍归类,再选方案,不要反复重录。
三、方案一:手工登录 + 会话注入(最快)¶
适用:验证码、扫码、SSO、前端加密。核心思路是绕开登录动作,直接给扫描器一个有效会话。
3.1 拿到会话凭证¶
用浏览器/Fiddler:
- 手工完成登录;
- 打开开发者工具 → Application → Cookies,或 Fiddler 里看任意业务请求的
Cookie头; - 复制完整 Cookie 串(注意包含
HttpOnly的那些,控制台document.cookie看不到,必须从请求头或 Fiddler 取); - 如果鉴权是
Authorization: Bearer,复制整个头。
3.2 在 AppScan 里配置¶
不同版本菜单名略有差异,路径基本是:
若整个 Cookie 串都要带,选择"自定义 Header"更稳:
Bearer 同理:
3.3 验证会话是否被带上¶
扫描前先做一次"仅探索"(Explore Only),然后在扫描日志/请求详情里确认:
- 业务请求是否带上了你配置的 Cookie/Header;
- 返回码是 200 而不是 302;
- 响应里出现了登录后才有的字段(用户名、订单列表)。
如果仍是 302,检查:
- Cookie 是否过期(很多系统 30 分钟无操作即失效);
- 是否漏了
HttpOnly的会话 Cookie; - 是否还有
X-Tenant-Id、X-Requested-With等自定义头; - 是否有 IP 绑定(换机器后会话失效)。
四、方案二:HAR 导入(最贴近真实浏览器)¶
AppScan 支持导入 HAR 作为探索数据,也可用于登录序列。HAR 是浏览器/Fiddler 都能导出的标准格式,能完整保留 Header、Cookie、POST Body、加密后的密码。
4.1 从浏览器导出¶
注意:
- 必须勾 Preserve log,否则 302 跳转后前面的请求会被清空;
- 导出前把无关的静态资源请求清掉,文件越小导入越快;
- HAR 里含真实 Cookie 与密码密文,按敏感数据管理,别进 Git。
4.2 从 Fiddler 导出¶
Fiddler → Tools → Options → HTTPS → 勾选 Capture HTTPS CONNECTs / Decrypt HTTPS traffic
→ 手工登录并浏览
→ File → Export Sessions → Selected Sessions
→ 格式选择 "HTTPArchive v1.2" → 保存 login.har
Fiddler 导出 HAR 比浏览器更灵活:可以只选登录相关会话,也可以把 App 的流量一起导出(前提是已解决证书信任)。
4.3 导入 AppScan¶
文件 → 导入 → 探索数据(Import → Explore Data)
→ 选择 login.har
→ 选择"作为登录序列"或"作为探索数据"
→ 配置扫描目标 URL 与范围 → 仅测试 / 完整扫描
版本差异说明:部分版本在"扫描配置 → 登录管理 → 导入登录序列"里导入 HAR,部分版本在"文件 → 导入"。找不到时用关键词 HAR、Import、Login Sequence 在菜单里搜。
4.4 导入后必须做的三件事¶
- 剔除无关域名:HAR 里往往混着埋点、CDN、第三方支付。把这些域名从扫描范围排除,否则会扫到未授权目标。
- 检查会话是否仍然有效:HAR 是历史流量,Cookie 可能已过期。导入后先跑"仅探索",看是否 200。
- 补录登录后的业务流量:只导入登录请求,AppScan 不会自动知道后续接口。最好把登录后 20~50 个关键请求一起导入,作为爬虫的种子。
4.5 用脚本裁剪 HAR¶
import json
SRC = "login.har"
DST = "login_trimmed.har"
ALLOW = ("app.example.com",)
with open(SRC, encoding="utf-8") as f:
har = json.load(f)
entries = [
e for e in har["log"]["entries"]
if any(host in e["request"]["url"] for host in ALLOW)
]
# 去掉静态资源,减少导入噪音
STATIC = (".js", ".css", ".png", ".jpg", ".svg", ".woff", ".ico")
entries = [e for e in entries
if not e["request"]["url"].split("?")[0].endswith(STATIC)]
har["log"]["entries"] = entries
with open(DST, "w", encoding="utf-8") as f:
json.dump(har, f, ensure_ascii=False)
print("保留", len(entries), "条请求")
4.6 从 HAR 提取会话头¶
导入失败时,可以直接从 HAR 里把最后一次业务请求的 Cookie 提出来,用于方案一:
import json
har = json.load(open("login.har", encoding="utf-8"))
cookie = None
for entry in reversed(har["log"]["entries"]):
for h in entry["request"]["headers"]:
if h["name"].lower() == "cookie":
cookie = h["value"]
break
if cookie:
break
print("Cookie:", cookie)
五、方案三:pcap → Fiddler → HAR¶
有些场景只能拿到 pcap(例如 App 流量、无法装代理的设备),流程是:
Wireshark/tcpdump 抓 .pcap/.pcapng
→ Fiddler: File → Import Sessions → Packet Trace
→ Fiddler: File → Export Sessions → HTTPArchive v1.2
→ AppScan 导入 HAR
关键限制:
- HTTPS 流量必须有密钥才能还原。Fiddler 导入 pcap 时如果无法解密,只能看到 TLS 密文,导出的 HAR 里没有可用请求。
- 因此这条路只适用于 HTTP、或已通过
SSLKEYLOGFILE解密的场景。 - 用 tcpdump 抓的时候尽量全量:
tcpdump -i any -s 0 -w cap.pcapng host 10.0.0.5。
# 有密钥日志时,Wireshark 解密后再导出
export SSLKEYLOGFILE=/tmp/sslkey.log
# Wireshark: Preferences → Protocols → TLS → (Pre)-Master-Secret log
# 解密后 File → Export Objects → HTTP,或另存 pcapng 再交给 Fiddler
六、方案四:多步骤登录序列¶
适用于"登录前要先取 token"的系统,例如:
在 AppScan 的登录序列编辑器里:
- 添加第 1 步
GET /login; - 添加"提取参数"规则,用正则从响应中取 token:
- 添加第 2 步
POST /login,在 Body 里引用${csrfToken}; - 添加"登录验证"页:
/api/user/profile,并设置成功关键字(如"code":0); - 设置"会话失效检测":任意请求返回 302 到
/login时重新执行登录序列。
正则要贴着真实响应写,不要猜。先在 Fiddler 里看响应原文:
七、方案五:Manual Explore / 外部代理模式¶
AppScan 自带浏览器(Manual Explore)适合 SPA:
如果目标是 App 或不能装 AppScan 客户端的设备,用"外部代理"模式:把设备代理指向 AppScan 监听端口,手工操作,AppScan 记录流量。
注意:
- AppScan 的代理默认只监听本机,设备要连需要在设置里允许外部连接;
- HTTPS 需要设备信任 AppScan 的 CA,Android 7+ 还要装进系统证书;
- 外部代理模式下一定要限定目标范围,避免把设备上的其他流量一起扫。
八、会话中途失效怎么办¶
长扫描(几小时)必然遇到会话过期,表现为后半段全是 302/401,漏洞结果不可信。
三种处理:
- 会话失效检测 + 自动重登录:在登录管理里配置检测规则(URL 包含
/login或响应含"请登录"),触发重跑登录序列。 - 交互式提示:选择"提示输入",扫描中断时人工完成验证码/OTP。适合一次性任务。
- 延长会话:测试环境临时调长 session TTL,或给扫描账号配置"免超时"策略(需授权)。
无论哪种,扫描后都要验证会话有效性。
九、扫描后校验:确认真的扫到了业务¶
不要只看"扫描完成"。
9.1 覆盖率对比¶
# 从 HAR 提取登录后访问过的 URL,与扫描结果对比
import json, re
har = json.load(open("login.har", encoding="utf-8"))
urls = {e["request"]["url"].split("?")[0] for e in har["log"]["entries"]}
print("HAR 中的接口数:", len(urls))
for u in sorted(urls)[:30]:
print(u)
在 AppScan 的"应用树/URL 列表"里搜索这些路径,缺失的关键接口说明爬虫没覆盖到,需要手工补充探索数据。
9.2 状态码分布¶
在扫描结果的"请求/响应"里随机抽查 10 条业务请求,确认响应体是真实数据而不是登录页 HTML。
9.3 误报排查¶
会话失效会制造两类假漏洞:
| 假漏洞 | 成因 |
|---|---|
| 开放重定向 | 未登录时 302 到登录页,被识别为"可跳转外部地址" |
| 会话令牌未更新 / 会话固定 | 登录页本身的会话行为,不是业务问题 |
| 敏感信息泄露 | 登录页 HTML 里的版本号、框架信息 |
处理:把登录页与静态资源加入排除规则,或在报告中标注"未认证状态下的结果"。
十、范围与合规¶
- 只扫描授权域名,第三方(支付、地图、埋点)必须排除;
- 导入的 HAR 含真实账号与 Cookie,扫描结束后删除;
- 不在生产环境开启主动扫描的高风险策略(SQL 注入、命令注入的破坏性 payload);
- 扫描产生的测试账号、上传文件要清理;
- 报告里注明登录方式与扫描时间段,便于复现。
十一、常见问题对照¶
| 现象 | 根因 | 处理 |
|---|---|---|
| 录制提示"未检测到登录" | 登录是 XHR,页面未跳转 | 用 HAR 导入或多步骤序列 |
| 导入 HAR 后全 302 | Cookie 已过期 | 重新导出,或改用会话注入 |
| 只有登录页被扫 | 未提供登录后种子 URL | HAR 里补 20~50 条业务请求 |
| 扫描很慢且结果很少 | 范围过大,爬虫被埋点域名拖住 | 排除第三方与静态资源 |
| 漏洞全是会话类 | 会话失效,扫的是未登录态 | 配置重登录,重扫 |
| App 流量抓不到 | SSL Pinning / 证书未信任 | 先解决代理与证书,再导出 HAR |
| pcap 导入 Fiddler 无内容 | HTTPS 未解密 | 设置 SSLKEYLOGFILE 或用代理抓 |
十二、检查清单¶
- 已确认登录障碍类型(验证码/token/SSO/加密/扫码)
- 会话凭证包含 HttpOnly Cookie 与自定义头
- HAR 导出时勾选了 Preserve log,含完整 302 链
- 导入前剔除了第三方域名与静态资源
- 扫描范围只含授权目标
- 配置了会话失效检测或重登录
- 扫描后抽查业务请求为 200 且含真实数据
- 302/401 占比正常,误报已排除
- 测试数据与 HAR 文件已清理