4. 身份认证测试(口令与令牌)

身份认证是接口安全的第一道门。等保三级明确要求“对登录用户进行身份标识和鉴别”。说白了,如果这关没守住,后面所有防线都是摆设。我做过不少合规项目,**超过70%的中危漏洞都出在认证环节**。今天就聊三个最容易出事的点:弱口令爆破、多因素认证绕过、令牌泄露检查。

核心要点: 身份认证测试不是简单地猜密码,而是要验证整个认证链是否被“旁路”或“降级”。

4.1 弱口令爆破测试

弱口令是最古老也是最有效的攻击方式。攻击者拿着字典,对着登录接口一顿猛试。你我心里都清楚,很多系统上线后默认密码没改,或者改成了“Admin@123”这种看起来复杂、实际脆弱的密码。

测试方法:

  • 字典准备:至少包含 top5000 常见组合(如 password、123456、qwerty、企业名+年份)。我个人习惯在 SecLists 基础上添加从目标信息中提取的专属词(公司缩写、电话区号等)。
  • 工具选型:Burp Intruder(适合小规模)、hydra(支持多协议)、或自己写脚本(例如用 Python + requests 配合线程池)。
  • 速率控制:等保要求“应限制非法登录次数”。所以测试前先确认接口有没有验证码或锁定策略。我曾在项目中遇到过,爆破到第5次就被锁了15分钟,反而暴露了安全机制——这是好事。
Tip: 测试前先用一个错误账号尝试登录5次,观察是否返回“账号已锁定”或验证码刷新。如果有锁定策略,需要调整测试频率(比如每分钟3次),避免触发熔断。

代码示例: 一个简单的弱口令爆破脚本片段(仅用于授权测试):

import requests

url = "https://api.target.com/login"
headers = {"Content-Type": "application/json"}
passwords = ["123456", "password", "admin123", "Target@2024"]

for pwd in passwords:
    data = {"username": "admin", "password": pwd}
    resp = requests.post(url, json=data, headers=headers, timeout=5)
    if resp.status_code == 200 and "" in resp.text:
        print(f"[+] 成功!密码:{pwd}")
        break
    else:
        print(f"[-] 尝试 {pwd} 失败")

这里要注意,等保对口令复杂度有硬性要求(长度≥8,含大小写字母、数字、特殊字符)。我曾经在一个政府项目中,发现所有管理员口令都符合 L1 级复杂度,但居然允许连续三次输错不锁定——这属于认证策略缺失,也是等保扣分项。

Warning: 爆破测试不要用生产环境的真实用户账号!一定要先申请测试账号,并在完成后通知安全团队清理日志。

4.2 多因素认证绕过测试

MFA 本应是强力防御,但实现不当反而变成纸老虎。常见的 MFA 形式有短信验证码、TOTP、生物识别。我们重点测三类绕过手法:

  1. 前端绕过:MFA 验证只在前端 JS 中判断,拦截请求后端就直接登录成功。我见过一个移动端 App,通过抓包发现登录接口返回两个字段 —— “mfa_required: true” 和 “session_”。把 “mfa_required” 改成 false,居然直接通过。
  2. 降级攻击:某些系统支持“先登录,后验证 MFA”,但在降级到纯密码登录的旧接口上没有移除 MFA 要求。比如 /api/v1/login 要求 MFA,但 /api/v0/login 直接返回 。我建议你在测试时把 URL 版本号从 v2 依次降到 v0 试试。
  3. 验证码重放:短信验证码通常有效期为5分钟,但有些系统未做一次性校验。拿到同一个验证码可以反复使用。我曾经在渗透测试中,用昨天收到的验证码居然还能登录——因为服务端只校验了码本身,没绑定 session。
绕过方式 检测方法 风险等级
前端逻辑绕过 修改接口返回中的 mfa_required 字段 高
版本降级 枚举旧版本 API 路径 中
验证码重放 捕获有效验证码,延迟发送或重复发送 高
短信轰炸 短时间内大量调用发送验证码接口 中
重点检查: 服务端是否在 所有 需要 MFA 的接口都强制执行校验?特别是密码找回、敏感操作(修改手机、提现)等场景。
Tip: 测试 MFA 绕过时,先做一次正常登录抓取完整流程,再尝试跳过第二步。如果发现接口 B 直接返回了 ,而接口 A 需要 MFA,那大概率存在绕过。

4.3 令牌泄露检查

不管用 JWT 还是传统 Session ,只要令牌被泄漏,攻击者就能冒用身份。我们重点查三个泄漏途径:

  • 日志与错误信息:登录日志、错误堆栈里是否明文记录了 ?我见过某系统在调试日志里打印完整 JWT,而且日志文件被搜索引擎收录了。
  • URL 参数与 Referer:有些系统为了兼容老旧客户端,把 放在 query string 里(如 ?=xxx)。这会导致 Referer 泄漏给第三方。我建议你直接用 grep 搜索项目代码中所有 "=" 的拼接写法。
  • 浏览器存储:localStorage 默认没有 HttpOnly,XSS 可以任意读取。生产环境务必使用 HttpOnly + Secure + SameSite=Strict 的 Cookie。

JWT 还有个特有风险:签名算法未指定或允许 "none"。攻击者可以把 alg 改为 none,直接伪造任意 payload。我曾在内网渗透时遇到一个自研网关,JWT 的 header 里写 "alg": "none",服务端居然认了。这属于开发框架配置遗漏。

// 一个常见的 JWT payload(千万别这么写)
{
  "sub": "admin",
  "role": "super_admin",
  "exp": 9999999999,   // 过期时间过大
  "iat": 1615000000
}
Warning: 令牌检查时不要只看本系统。有些环节会通过 HTTP 头跨系统传递 (比如 SSO),要验证是否会被中间网关记录。

好了,这三个方向基本覆盖了等保“身份认证”的大部分检查项。下面我把整个知识体系画成一张图,方便你对照。

身份认证测试知识点框架 身份认证测试 弱口令爆破 MFA绕过 令牌泄露 字典与频率 账号锁定策略 前端/降级绕过 验证码重放 日志/URL泄漏 JWT alg=none 注意:三个分支必须覆盖登录注册、密码找回、敏感业务接口 每个点都要验证是否在服务端强制而非前端