01 鉴权不是黑盒,是测试左移的第一道防线
测试左移,不是一句口号,是一场战争。当开发还在写代码,测试已经发现了接口鉴权的漏洞,这才是真正的“左移”。但现实很骨感:90%的测试人员把鉴权当作黑盒,只验证“有权限”和“无权限”两个场景,结果线上事故频发。

鉴权漏洞,是测试左移的照妖镜。
接口测试的核心不是测功能,是测安全。Cookie、Token、Signature三大鉴权机制,每一个都是攻防的焦点。Cookie被劫持,Token被伪造,Signature被重放,这些不是理论,是每天发生的事故。
一个真实的案例:某电商平台,测试只验证了登录后的接口调用,忽略了未登录状态下接口的鉴权逻辑。结果上线当天,攻击者直接调用商品详情接口,绕过登录获取了所有用户信息。这个漏洞,测试左移就能发现。
测试左移的核心是:在开发阶段介入,用代码思维理解鉴权机制。你不需要成为安全专家,但必须掌握三大鉴权的测试方法。下面,我们就逐一拆解。
02 Cookie鉴权:最古老也最脆弱的防线
Cookie鉴权,本质是服务器在用户浏览器种下一个“身份标签”。但这个标签,可以被窃取、伪造、重放。
测试Cookie鉴权,就是测试信任的边界。
Cookie鉴权的测试要点:
1. 会话固定攻击:服务器是否在登录后更新Session ID?不更新,攻击者可诱导用户使用已知的Session ID。
2. Cookie劫持:是否使用HttpOnly标记?没有,JavaScript可直接读取Cookie。
3. Cookie过期:是否设置合理的过期时间?永久有效,等于没有鉴权。
测试代码示例(Python requests):
python
import requests
# 模拟未登录状态调用接口
session = requests.Session()
response = session.get('https://api.example.com/user/info')
print(f"未登录状态码: {response.status_code}") # 期望返回401或403
# 模拟登录后获取Cookie
login_data = {'username': 'test', 'password': 'test123'}
login_response = session.post('https://api.example.com/login', data=login_data)
print(f"登录后Cookie: {session.cookies.get_dict()}")
# 验证Cookie中是否有HttpOnly标记
for cookie in session.cookies:
print(f"Cookie名称: {cookie.name}, HttpOnly: {cookie.has_nonstandard_attr('HttpOnly')}")
测试左移的关键点:在开发设计阶段,就要确认Cookie的Secure和HttpOnly标记是否开启。这两个标记,能挡住80%的Cookie劫持攻击。
Cookie鉴权的另一个测试场景:跨域鉴权。如果接口支持跨域,是否限制了Origin?不限制,攻击者可在任意网站发起CSRF攻击。
测试方法:修改请求头中的Origin字段,验证服务器是否校验。
python
# CSRF测试
headers = {'Origin': 'https://malicious-site.com'}
response = requests.post('https://api.example.com/transfer',
data={'amount': 1000},
cookies=session.cookies,
headers=headers)
print(f"跨域请求结果: {response.status_code}") # 期望返回403
Cookie鉴权的底线:所有敏感操作(转账、修改密码),必须二次确认。测试左移,就是把这些规则写进测试用例,而不是等上线再修。
03 Token鉴权:JWT不是万能钥匙
Token鉴权,尤其是JWT(JSON Web Token),是目前最流行的鉴权方式。但它不是银弹,测试不到位,漏洞比Cookie更多。
JWT的签名,是测试的护城河。
JWT由三部分组成:Header、Payload、Signature。测试重点:
1. 签名算法:是否使用弱算法(如HS256)?是否允许“none”算法?
2. Payload泄露:是否包含敏感信息(如密码、手机号)?
3. Token过期:是否设置合理的过期时间?Refresh Token机制是否安全?
测试代码示例:
python
import jwt
import requests
# 测试JWT签名算法
def test_jwt_algorithm():
# 使用'none'算法伪造Token
fake_token = jwt.encode({'user_id': 1}, key='', algorithm='none')
headers = {'Authorization': f'Bearer {fake_token}'}
response = requests.get('https://api.example.com/user/info', headers=headers)
print(f"none算法伪造Token结果: {response.status_code}") # 期望返回401
# 使用弱密钥破解
weak_token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxfQ.xxx"
# 使用常见密码字典尝试破解
common_keys = ['secret', 'password', '123456']
for key in common_keys:
try:
decoded = jwt.decode(weak_token, key, algorithms=['HS256'])
print(f"破解成功! 密钥: {key}")
break
except:
pass
# 测试Payload泄露
def test_payload_leak():
# 解析JWT的Payload部分
token = "your_jwt_token_here"
payload = jwt.decode(token, options={"verify_signature": False})
sensitive_fields = ['password', 'phone', 'credit_card']
for field in sensitive_fields:
if field in payload:
print(f"敏感信息泄露: {field}")
测试左移的实践:在开发评审阶段,就要确认JWT的签名算法、过期时间、Payload内容。这些不是运维的事,是测试的事。
Token鉴权的另一个测试场景:Refresh Token机制。很多系统使用Access Token(短时效)+ Refresh Token(长时效)。测试要点:
- ►Refresh Token是否可以被重用?
- ►Access Token过期后,是否能在不验证身份的情况下刷新?
- ►是否支持Token吊销?
测试代码:
python
# 测试Refresh Token重用
def test_refresh_token_reuse():
# 第一次刷新
refresh_response = requests.post('https://api.example.com/refresh',
data={'refresh_token': 'xxx'})
new_access_token = refresh_response.json()['access_token']
# 第二次使用相同的Refresh Token
second_response = requests.post('https://api.example.com/refresh',
data={'refresh_token': 'xxx'})
print(f"Refresh Token重用结果: {second_response.status_code}") # 期望返回403
Token鉴权的底线:签名算法必须使用RS256(非对称加密),Payload不能包含敏感信息,Access Token过期时间不超过15分钟。测试左移,就是把这些标准变成自动化测试用例。
04 Signature鉴权:防篡改的终极武器
Signature鉴权,是API安全的最后一道防线。它通过签名算法,确保请求的完整性、真实性和不可否认性。
Signature鉴权,测试的是算法的严谨性。
Signature鉴权的核心要素:
1. 签名参数:是否包含时间戳(timestamp)和随机数(nonce)?
2. 签名算法:是否使用HMAC-SHA256或RSA-SHA256?
3. 重放攻击防护:是否校验时间戳和随机数的唯一性?
测试代码示例(HMAC-SHA256签名):
python
import hashlib
import hmac
import time
import requests
def generate_signature(params, secret_key):
# 参数排序
sorted_params = sorted(params.items())
# 拼接字符串
sign_str = '&'.join([f"{k}={v}" for k, v in sorted_params])
# HMAC-SHA256签名
signature = hmac.new(secret_key.encode(), sign_str.encode(), hashlib.sha256).hexdigest()
return signature
# 测试签名验证
def test_signature_verification():
secret_key = 'test_secret'
params = {
'user_id': 1,
'timestamp': int(time.time()),
'nonce': 'random_string_123'
}
signature = generate_signature(params, secret_key)
params['signature'] = signature
# 正常请求
response = requests.get('https://api.example.com/user/info', params=params)
print(f"正常签名请求: {response.status_code}") # 期望200
# 篡改参数
tampered_params = params.copy()
tampered_params['user_id'] = 2
response = requests.get('https://api.example.com/user/info', params=tampered_params)
print(f"篡改参数请求: {response.status_code}") # 期望403
测试左移的关键点:在开发阶段,就要确认签名算法是否包含时间戳和随机数。这两个参数,是防重放攻击的基础。
Signature鉴权的测试场景:
1. 时间戳校验:是否允许过期的时间戳?允许,则可重放攻击。
2. 随机数去重:是否记录已使用的随机数?不记录,则可多次重放。
3. 签名参数排序:是否按固定顺序排序?不排序,签名结果不一致。
测试代码:
python
# 测试时间戳过期
def test_timestamp_expiry():
params = {
'user_id': 1,
'timestamp': int(time.time()) - 3600, # 1小时前的签名
'nonce': 'old_nonce'
}
signature = generate_signature(params, 'test_secret')
params['signature'] = signature
response = requests.get('https://api.example.com/user/info', params=params)
print(f"过期时间戳请求: {response.status_code}") # 期望403
# 测试随机数去重
def test_nonce_uniqueness():
params = {
'user_id': 1,
'timestamp': int(time.time()),
'nonce': 'same_nonce'
}
# 第一次请求
signature = generate_signature(params, 'test_secret')
params['signature'] = signature
response1 = requests.get('https://api.example.com/user/info', params=params)
# 第二次使用相同随机数
response2 = requests.get('https://api.example.com/user/info', params=params)
print(f"重复随机数请求: {response2.status_code}") # 期望403
Signature鉴权的底线:签名算法必须包含时间戳和随机数,且服务器必须校验这两者的有效性。测试左移,就是把这些校验规则写进代码审查清单。
---
鉴权测试不是终点,是测试左移的起点。 在开发阶段发现一个鉴权漏洞,等于拯救一次线上事故。Cookie、Token、Signature,每一个都是攻防的战场。测试人员要做的,不是等代码写完了再测,而是在设计阶段就介入,用代码思维拆解鉴权逻辑。
记住:鉴权漏洞,测试左移就能发现。发现不了,是因为你还没开始左移。
声明:本站部分稿件版权来源于网络,如有侵犯版权,请及时联系我们。