news 2026/7/5 9:24:51

JWT安全攻防实战:从签名算法绕过到密钥混淆的5大漏洞解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
JWT安全攻防实战:从签名算法绕过到密钥混淆的5大漏洞解析

1. 项目概述:从靶场到实战的JWT安全攻防

最近在复盘一些渗透测试项目时,发现JWT(JSON Web Token)相关的安全问题出现频率越来越高。很多开发团队在引入JWT作为认证方案后,往往只关注其带来的便利性,却忽视了其自身的安全配置和潜在风险。这让我想起之前在CTFHub靶场里专门练习JWT漏洞的场景,那些精心设计的挑战,恰恰是现实世界中漏洞的缩影。从靶场的“解题”思维,切换到真实渗透测试的“发现风险”思维,中间需要跨越的不仅是技术点,更是对漏洞原理、利用场景和修复方案的深度理解。

JWT本质上是一种开放标准,用于在各方之间安全地传输信息作为JSON对象。由于其紧凑、自包含的特性,它特别适合用于分布式站点的单点登录、API认证等场景。一个典型的JWT由三部分组成:头部、载荷和签名,中间用点分隔,形如xxxxx.yyyyy.zzzzz。问题往往就出在开发者对这三部分的生成、验证和处理的逻辑理解不透彻上。在CTF中,我们可能只需要找到一种特定的攻击手法拿到flag;但在真实渗透中,我们需要系统性地审视整个JWT的生命周期,找出其中任何一个环节的薄弱点。

这篇文章,我将结合在CTFHub靶场中的实战经验,以及真实渗透测试项目中遇到的案例,系统梳理JWT安全漏洞的5种核心利用手法。更重要的是,我会详细拆解每一种手法背后的原理、在真实环境中的利用条件、具体的操作步骤,并给出具有可操作性的修复建议。无论你是安全研究员、渗透测试工程师,还是负责开发维护的工程师,理解这些内容都能帮助你更好地构建和防御基于JWT的认证体系。

2. JWT安全漏洞的5种核心利用手法深度解析

JWT的安全问题,大多源于实现上的疏漏而非协议本身的设计缺陷。攻击者正是利用了这些疏漏,伪造、篡改或滥用Token,从而绕过认证、提升权限或窃取信息。下面我们逐一拆解这五种常见手法。

2.1 手法一:签名算法置空与“None”攻击

这是JWT安全中最经典也最容易被忽视的一种攻击方式。其核心原理在于,JWT规范允许使用“none”算法,即不进行签名验证。这种设计本意是用于调试或某些不需要完整性的场景,但如果在生产环境中服务端错误地接受了“none”算法,攻击者就可以伪造任意Token。

漏洞成因深度分析:JWT的头部(Header)中有一个alg字段,用于声明签名所使用的算法,如HS256、RS256等。当服务端接收到一个JWT时,它需要根据这个alg字段的值来选择对应的验证逻辑。漏洞产生的关键在于,服务端的验证代码存在逻辑缺陷。一种常见的有缺陷的验证逻辑伪代码如下:

def verify_token(token): header = decode_header(token) # 解码头部 alg = header.get('alg') if alg == 'HS256': # 使用密钥验证HMAC签名 return verify_hmac(token, secret_key) elif alg == 'RS256': # 使用公钥验证RSA签名 return verify_rsa(token, public_key) # 缺少对‘none’或其他未知算法的拒绝逻辑! # 或者错误地认为‘none’算法等同于验证通过 else: # 错误示例:直接返回True return True

从代码中可以看出,如果服务端没有显式拒绝algnone的Token,或者错误地将none等同于验证成功,那么攻击者就可以构造一个头部为{"alg":"none","typ":"JWT"},载荷为任意内容(例如将用户名改为admin),签名部分为空的Token。服务端在处理时,发现算法是none,可能就会跳过签名验证步骤,直接信任载荷中的信息。

真实环境利用场景与实操:在真实的黑盒渗透测试中,我们如何发现和利用这类漏洞?首先,你需要获得一个有效的JWT(通常通过登录获取)。然后,使用Burp Suite的Decoder或类似工具,对其进行Base64解码,观察其头部。接着,尝试篡改。

  1. 捕获Token:使用代理工具拦截含有JWT的请求(通常在Authorization: Bearer头或Cookie中)。
  2. 修改头部:将头部的alg字段改为none。注意,JWT各部分都是Base64Url编码的,修改后需要重新编码。同时,必须将签名部分置空
  3. 发送请求:将篡改后的Token替换原Token,重放请求。
  4. 观察响应:如果请求成功(例如返回了管理员数据或访问了未授权接口),则说明存在漏洞。

注意:现代成熟的JWT库(如java-jwtpyjwt)默认会拒绝alg=none的Token。因此,这个漏洞多见于开发者自行实现JWT解析验证逻辑,或错误配置了第三方库的情况。在测试时,也可以尝试将alg改为NoneNONEnOnE等大小写变种,以绕过一些简单的字符串过滤。

修复建议:在服务端验证JWT时,必须显式指定允许的算法列表,并且拒绝任何不在列表中的算法,尤其是none。以Python的PyJWT库为例,正确的做法是:

import jwt # 错误做法:不指定算法,库可能会使用头部声明的算法(易受攻击) # decoded = jwt.decode(token, 'your-secret-key') # 正确做法:使用`algorithms`参数明确指定可接受的算法 decoded = jwt.decode( token, 'your-secret-key', algorithms=['HS256'] # 明确只接受HS256算法 )

这样,即使攻击者传入alg: none的Token,jwt.decode函数也会因为none不在algorithms列表中而直接抛出InvalidAlgorithmError异常。

2.2 手法二:密钥混淆攻击(HS256与RS256)

这种攻击手法比“none”攻击更隐蔽,需要对非对称加密和对称加密有基本的理解。JWT常用的签名算法有HS256(HMAC with SHA-256,对称加密)和RS256(RSA Signature with SHA-256,非对称加密)。

漏洞成因深度分析:

  • HS256:使用同一个密钥进行签名和验证。密钥必须保密。
  • RS256:使用私钥签名,公钥验证。私钥保密,公钥可以公开。

漏洞产生于服务端代码错误地允许算法被篡改。假设一个应用本应使用RS256,其验证逻辑是:从Token头部读取alg,如果是RS256,就用预置的公钥去验证签名。攻击者可以尝试以下步骤:

  1. 将头部algRS256改为HS256
  2. 服务端代码有缺陷,它看到alg: HS256后,错误地使用了原本用于验证RS256的公钥作为HMAC的对称密钥,来验证签名。
  3. 攻击者只需要知道这个公钥(通常是公开的),就可以用HS256算法和这个公钥作为密钥,伪造一个有效的签名。

关键在于,服务端在验证时,没有将算法与密钥进行绑定。用于RS256验证的公钥,被错误地用于HS256的验证逻辑。

真实环境利用场景与实操:利用此漏洞的前提是,攻击者能够获取到应用用于验证RS256签名的公钥。公钥有时会存放在/jwks.json/.well-known/jwks.json等端点,或者直接硬编码在前端JavaScript代码中。

  1. 信息收集:寻找应用的公钥。检查前端JS、已知的JWKS端点、甚至应用文档。
  2. 获取原始Token:正常登录获取一个有效的RS256签名的JWT。
  3. 篡改与伪造
    • 修改载荷(如将user: victim改为user: admin)。
    • 将头部alg改为HS256
    • 使用获取到的公钥作为HMAC的密钥,对新的头部和载荷进行HS256签名。
    • 生成新的Token。
  4. 重放测试:用伪造的Token替换原Token发送请求。

修复建议:服务端在验证JWT时,绝对不能依赖客户端可控制的头部alg字段来决定验证逻辑和所使用的密钥。正确做法是,应用在配置验证器时,就固定好算法和对应的密钥。

  • 如果使用HS256,则配置一个保密的对称密钥,并固定使用HS256算法验证。
  • 如果使用RS256,则配置公钥,并固定使用RS256算法验证。 同样以PyJWT为例,修复方式就是始终在decode时明确指定算法:
# 对于HS256服务 decoded = jwt.decode(token, 'strong-secret-key', algorithms=['HS256']) # 对于RS256服务 decoded = jwt.decode(token, public_key, algorithms=['RS256'])

这样,无论攻击者如何修改Token头部的alg,服务端都只用自己的预设算法和密钥去验证,从根本上杜绝了密钥混淆的可能。

2.3 手法三:弱密钥爆破与密钥泄露

这种手法更偏向于传统的密码学攻击,针对的是使用对称算法(如HS256)的JWT。如果签名密钥强度不够,或者密钥意外泄露,那么整个认证体系就会崩塌。

漏洞成因深度分析:HS256的安全性完全依赖于密钥的强度。密钥泄露的途径可能包括:

  1. 弱密钥:开发者使用简单、常见的字符串作为密钥,如secretpassword123456、应用名等。这些密钥可以被字典攻击轻松破解。
  2. 密钥硬编码:将密钥写在客户端代码、配置文件或代码仓库中,导致密钥可能被反编译、源码泄露或通过目录遍历获取。
  3. 密钥生成算法有缺陷:使用不安全的随机数生成器生成密钥,导致密钥可预测。

真实环境利用场景与实操:在渗透测试中,面对一个HS256签名的JWT,密钥爆破是常规手段。

  1. 识别算法:解码JWT头部,确认algHS256
  2. 准备字典:收集常见的JWT弱密钥字典。网络上有很多开源字典,包含成千上万个常见密钥。也可以根据目标应用名称、域名、公司名等生成定制字典。
  3. 使用工具爆破:推荐使用hashcatjwt-tool
    • 使用jwt-tooljwt-tool是专为JWT安全测试设计的工具,非常方便。
      python3 jwt_tool.py <JWT_TOKEN> -C -d /path/to/wordlist.txt
    • 使用hashcat:hashcat性能强大,模式16500对应JWT。
      # 将JWT格式转换为hashcat接受的格式(token::signature) echo -n "<JWT_TOKEN>" > jwt.hash hashcat -m 16500 jwt.hash /path/to/wordlist.txt
  4. 利用泄露密钥:一旦爆破出密钥,你就可以用这个密钥为任意载荷生成合法的签名,完全控制Token内容。

实操心得:爆破的成功率取决于字典的质量。除了通用弱密钥字典,一定要尝试与目标相关的词汇组合。有时,查看网页源代码、JavaScript文件甚至错误信息,可能会发现密钥的线索。在CTF靶场中,弱密钥往往设置得很明显;但在真实场景,密钥可能有一定复杂度,需要结合其他信息泄露漏洞(如Git源码泄露、配置文件泄露)来获取。

修复建议:

  1. 使用强密钥:对于HS256,密钥必须是足够长(如32字节以上)、随机的密码学安全字符串。可以使用安全的随机数生成器来生成。
  2. 密钥管理:绝对不要将密钥硬编码在客户端或公开的代码仓库中。应该使用安全的密钥管理系统,如云服务商的密钥管理服务,或在部署时通过环境变量注入。
  3. 定期轮换密钥:制定密钥轮换策略。但要注意,轮换会导致所有已签发的Token立即失效,需要配合合理的Token过期时间和刷新机制。
  4. 考虑升级算法:对于安全性要求极高的场景,应考虑使用RS256等非对称算法。即使公钥泄露,没有私钥也无法伪造签名,从根本上解决了对称密钥泄露的风险。

2.4 手法四:KID参数路径遍历与注入

kid(Key ID)是JWT头部的一个可选参数,用于指示在验证签名时应该使用哪个密钥。这在服务端维护了多个密钥(例如用于密钥轮换或不同租户)时非常有用。然而,如果服务端处理kid参数的方式不安全,就会引入严重漏洞。

漏洞成因深度分析:服务端通常会有一个密钥库(JWKS),根据kid来查找对应的密钥。漏洞出现在以下情况:

  • 路径遍历:如果kid参数被直接用于拼接文件路径(例如/keys/+kid),攻击者可以注入路径遍历序列(如../../../../etc/passwd),让服务端读取非预期的文件作为密钥。如果这个文件内容是已知的(如/dev/null是空,/proc/self/environ包含环境变量),攻击者就可能用这个“密钥”来伪造签名。
  • SQL注入:如果kid被直接用于数据库查询,可能引发SQL注入,进而导致密钥泄露或其他数据破坏。
  • 重定向攻击:如果kid是一个URL,服务端可能从这个URL获取密钥。攻击者可以控制这个URL指向自己服务器上的一个密钥文件,从而完全控制签名验证。

真实环境利用场景与实操:假设我们发现一个JWT的头部包含"kid": "key-123"

  1. 测试路径遍历:尝试修改kid../../../../etc/passwd。然后,我们需要用/etc/passwd文件的内容作为HMAC密钥,来为篡改后的载荷生成签名。由于/etc/passwd是公开可读的,我们知道它的内容。我们可以用这个内容作为密钥,使用HS256算法生成签名,构造一个“合法”的Token。
  2. 工具辅助jwt-tool可以自动化这个过程。
    python3 jwt_tool.py <JWT_TOKEN> -I -hc kid -hv "../../../../etc/passwd" -S hs256 -k /etc/passwd
    这个命令会注入kid,并用指定的文件作为密钥重新签名。
  3. 测试其他敏感文件:尝试/proc/self/environ(可能泄露环境变量,其中包含密钥)、/dev/null(空密钥)等。
  4. 测试URL重定向:尝试将kid改为http://attacker.com/key.jwk,观察服务端是否会发起网络请求(可通过自己服务器日志查看)。如果会,则攻击者可以托管一个自定义的JWKS,完全掌控验证密钥。

修复建议:

  1. 严格校验kid:将kid视为用户输入,进行严格的校验。只允许特定的、预定义的键名(白名单),并且禁止任何可能包含路径遍历字符(../\等)或URL协议(http://)的值。
  2. 间接映射:不要直接用kid拼接路径或查询。应该维护一个安全的映射表,将允许的kid映射到对应的密钥对象或安全存储路径。
  3. 限制JWKS URL:如果支持从URL获取JWKS,必须将URL限制在可信的、预配置的域名列表内,并验证HTTPS证书。
  4. 使用标准库:尽可能使用经过安全审计的标准JWT库,它们通常对这类参数有更安全的默认处理方式。

2.5 手法五:未经验证的头部与载荷篡改

即使签名验证本身是坚固的,如果应用在验证签名之后,错误地信任了Token头部或载荷中的某些字段,也可能导致逻辑漏洞。这与JWT本身的密码学安全无关,而是应用业务逻辑的缺陷。

漏洞成因深度分析:JWT签名验证只能保证Token自签发后未被篡改。但它不能保证Token里的信息在当前的业务上下文里是有效或合适的。常见的逻辑缺陷包括:

  • 信任ctytypcty表示内容类型,typ表示令牌类型。如果服务端代码根据这些字段来决定如何处理Token,而攻击者可以篡改它们,就可能触发不同的、有缺陷的解析逻辑。
  • 密钥ID混淆:类似于kid,头部可能有jkux5u等参数指向包含密钥的URL。如果应用在验证签名后,又根据这些参数去执行其他操作(如记录日志、查询数据库),而参数被篡改,可能导致SSRF或日志注入。
  • 载荷逻辑绕过:签名验证通过后,应用从载荷中读取user_idrole等信息进行授权。但如果授权逻辑有缺陷,例如只检查了role是否为admin,却没有检查user_id是否与当前会话绑定,攻击者就可以使用一个属于低权限用户但被篡改了role字段的Token(前提是你能获得这个Token的签名,这通常意味着你需要该用户的密钥或破解之)。

真实环境利用场景与实操:这种漏洞的利用更依赖于对目标应用业务逻辑的理解。

  1. 分析Token与业务逻辑:首先,你需要一个或多个有效Token,并理解应用如何使用它们。通过Burp Suite重放不同权限用户的请求,观察请求参数、响应差异。
  2. 测试头部参数影响:在确保签名有效的前提下(即你需要有正确的密钥或使用原Token),尝试修改头部字段。
    • 修改typJWTJWT+XML或其他值,观察响应是否变化,是否可能触发XML解析器导致XXE?
    • 修改cty,看是否会改变服务端对载荷内容的解析方式?
  3. 测试授权逻辑:这是更常见的场景。假设你有一个普通用户A的Token,其中"user_id": 1001, "role": "user"。你还有一个管理员用户B的Token(你无法获得),其中"user_id": 1, "role": "admin"。如果应用在验证签名后,仅根据role字段判断管理员权限,那么你可以尝试将用户A的Token中的role改为admin,然后用用户A的密钥重新签名(如果你能爆破或泄露用户A的密钥)。但在很多情况下,你无法做到。 更实际的场景是水平越权。如果应用在修改资源时,只从Token的user_id字段判断所有权,而不从数据库复核该Token对应的真实用户是否拥有该资源,那么攻击者就可以通过修改请求中的资源ID(如/api/user/1001/profile改为/api/user/1002/profile),配合自己的合法Token,来访问或修改他人数据。这里的漏洞不在JWT,而在业务接口的授权检查不完整。

修复建议:

  1. 签名验证后,不信任可控字段:理解jkux5ukid等字段仅在签名验证阶段有意义。验证通过后,业务逻辑不应再依赖这些可能来自客户端的字段。
  2. 完整的授权检查:这是最重要的原则。JWT中的声明(Claims)只能作为初始的、快捷的用户身份和权限提示。在进行任何敏感操作(尤其是写操作或访问他人数据)时,服务端必须进行完整的、基于数据库真实状态的授权检查。
    • 垂直越权防御:不仅检查role,还要将Token中的user_id与操作所涉及的用户身份进行比对。
    • 水平越权防御:对于数据访问,必须校验当前Token对应的用户,是否拥有其请求操作的目标数据的所有权。例如,在/api/orders/123接口中,需要检查订单123是否属于当前用户。
  3. 使用标准声明:优先使用JWT标准声明(如sub,iss,exp),并充分理解其含义。对于自定义声明,要有清晰的文档和严格的校验逻辑。

3. 从靶场到实战:渗透测试中的JWT审计流程

掌握了具体的攻击手法,我们需要将其融入到一个系统化的渗透测试流程中。以下是我在实际工作中总结的一套针对JWT的审计方法,它融合了自动化工具扫描和手动深度测试。

3.1 信息收集与Token识别

第一步永远是发现目标。JWT可能出现在多个地方:

  • HTTP头部:最常见的是Authorization: Bearer <token>
  • Cookie:有时会存储在Cookie中,名称可能是auth_tokenjwtsession等。
  • URL参数:较少见,但可能存在,如?token=<JWT>
  • Post Body:在部分API设计中,Token可能通过JSON body传递。

在Burp Suite中,你可以使用“Search”功能在整个项目范围内搜索正则表达式[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]*,来快速定位JWT。或者使用jwt-heartbreaker等Burp插件进行自动识别和标记。

3.2 自动化初步扫描与手动验证

不要完全依赖工具,但工具可以极大提高效率。将捕获到的JWT发送到Burp的JWT Editor插件或jwt_tool进行初步测试。

  1. 算法测试:工具会自动测试none算法、将RS256改为HS256等常见问题。
  2. 敏感信息扫描:解码载荷,查看是否包含敏感信息,如邮箱、手机号、内部ID、过长的权限列表等。这本身可能就是一种信息泄露。
  3. 过期时间检查:检查exp声明。是否存在exp?是否设置得过长(如数年)?这增加了Token泄露后的风险窗口。
  4. 工具结果研判:自动化工具可能会报出“疑似漏洞”。切勿直接相信。必须手动复现,理解其报出漏洞的原理和利用条件。例如,工具提示“密钥混淆可能”,你需要手动检查是否有公钥泄露,并尝试构造POC。

3.3 深度手动测试清单

在自动化扫描后,按照以下清单进行深度手动测试:

  1. 签名验证移除测试:直接删除签名部分(第三个点之后的所有内容),或者将签名改成任意字符串,看服务端是否还会接受。这能判断服务端是否真的在执行签名验证。
  2. 弱密钥爆破:针对HS256 Token,使用综合字典进行爆破。别忘了结合目标信息的定制字典。
  3. 参数注入测试:如果头部有kidjkux5u等参数,系统性地测试路径遍历、SSRF和SQL注入。
    • kid:../../../etc/passwd../../../../windows/win.inikey-123' OR '1'='1
    • jku:http://attacker-controlled.example.com/jwks.json
  4. 业务逻辑测试
    • 声明篡改:在能重新签名的情况下,尝试修改roleuser_idemail等声明,测试垂直和水平越权。
    • Token重复使用:注销或修改密码后,旧Token是否立即失效?
    • 多端一致性:在Web端登录后获得的JWT,能否直接在移动端API使用?反之亦然?这有助于理解Token的签发和验证是否统一。
  5. 密钥管理评估:尝试寻找密钥泄露的迹象。检查前端JS源码、Git泄露、目录遍历读取配置文件、错误信息等。

3.4 问题排查与漏洞确认技巧

在测试过程中,你可能会遇到各种响应,如何判断漏洞是否存在?

  • 响应状态码差异:对比正常Token、篡改后Token、无Token三种情况下的响应码。如果篡改后返回200或302(成功状态),而签名无效的Token返回401/403,那很可能存在漏洞。但如果都返回同样的错误页面,可能需要进一步分析响应内容。
  • 响应时间差异:有时漏洞存在,但服务端会统一返回错误信息。此时观察响应时间可能有奇效。例如,在测试密钥混淆时,如果服务端错误地尝试用公钥进行HMAC运算,这个计算过程可能比直接返回“无效签名”要慢几十毫秒。使用Burp Suite的Repeater模块,多次发送请求并对比响应时间。
  • 错误信息泄露:仔细阅读所有错误响应。错误信息中可能泄露使用的库类型、密钥的线索(如“无效的密钥格式”)甚至堆栈跟踪。
  • 旁路信息:观察登录、刷新Token等接口的行为。有时,密钥可能通过其他不安全的端点泄露。

实操心得:真实环境的渗透测试往往没有CTF靶场那么“标准”。服务端可能有WAF、有复杂的负载均衡、有自定义的错误处理。你的Payload可能需要编码、可能需要分多次请求、可能需要结合其他漏洞(如XSS先窃取Token)。保持耐心,像拼图一样将各种信息组合起来,才能最终确认漏洞的存在和可利用性。

4. 面向开发者的JWT安全加固指南

作为渗透测试人员,我们的目标不仅是发现漏洞,更是帮助客户修复风险。以下是一份可以直接交付给开发团队的安全加固建议。

4.1 安全配置清单

  1. 选择强算法并固定使用

    • 首选RS256等非对称算法。私钥安全存储于服务端,公钥可用于验证,即使公钥泄露也无法伪造Token。
    • 如果必须使用HS256,确保密钥是密码学安全的随机字符串(长度>=32字节),并通过安全的方式管理(如环境变量、密钥管理服务)。
    • 绝对禁止使用none算法。在代码中显式声明允许的算法列表。
  2. 使用经过审计的成熟库

    • 避免自己手写JWT解析和验证代码。使用社区活跃、经过安全审计的官方库,如:
      • Java:java-jwt/jjwt
      • Python:PyJWT
      • Node.js:jsonwebtoken
      • Go:golang-jwt/jwt
    • 定期更新这些库到最新版本,以修复已知漏洞。
  3. 严格校验声明

    • 过期时间:必须校验exp,并设置合理的短有效期(如15-30分钟)。
    • 生效时间:校验nbf(Not Before)。
    • 签发者:校验iss,确保Token来自可信的签发方。
    • 受众:校验aud,确保Token是发给本应用的。
    • 在库的验证函数中设置这些校验参数。
  4. 安全的密钥/密钥ID管理

    • 对于kid,实施严格的白名单校验,防止路径遍历和注入。
    • 对于JWKS URL,只允许配置在可信列表内的HTTPS端点。
    • 私钥和HS256的对称密钥必须视为最高机密,绝不能出现在客户端代码、版本库或配置文件中。

4.2 生命周期管理与纵深防御

  1. 实现Token吊销机制:JWT本身是无状态的,吊销困难。可以通过维护一个短小的“吊销列表”(存储已注销但未过期的Token ID)或在服务端维护一个“版本号”声明来实现简易吊销。用户注销或修改密码时,递增其版本号,验证Token时检查版本是否匹配。
  2. 采用短有效期与刷新令牌模式:访问令牌设置短有效期(如15分钟),配合一个长有效期的刷新令牌来获取新的访问令牌。这样即使访问令牌泄露,攻击窗口也很小。刷新令牌必须安全存储(如HttpOnly Cookie),且其使用频率低,泄露风险小。
  3. 记录与监控:记录所有JWT验证失败的事件(尤其是签名无效、算法不匹配、kid异常等),并设置告警。这些日志是发现攻击行为的重要线索。
  4. 业务层二次授权:这是最重要的纵深防御措施。JWT验证是认证,不是授权。在执行业务逻辑前,必须根据当前用户的真实身份(可从数据库查询)和操作目标,进行完整的权限检查。

4.3 常见错误配置与修复代码示例

错误示例1:依赖头部alg

# 危险:依赖客户端控制的alg def dangerous_verify(token): decoded = jwt.decode(token, verify=False) # 先解码不看签名 alg = decoded['header']['alg'] if alg == 'HS256': key = SECRET_KEY elif alg == 'RS256': key = PUBLIC_KEY # 这里用动态的alg和key去验证,存在密钥混淆风险 return jwt.decode(token, key, algorithms=[alg])

修复后:

# 安全:固定算法和密钥 def safe_verify_hs256(token): # 明确指定算法和密钥,忽略头部alg try: payload = jwt.decode(token, SECRET_KEY, algorithms=['HS256']) return payload except jwt.InvalidTokenError: return None def safe_verify_rs256(token): # 明确指定算法和公钥 try: payload = jwt.decode(token, PUBLIC_KEY, algorithms=['RS256']) return payload except jwt.InvalidTokenError: return None

错误示例2:未校验标准声明

payload = jwt.decode(token, SECRET_KEY, algorithms=['HS256']) # 直接使用payload,未检查是否过期 user_id = payload['user_id']

修复后:

try: payload = jwt.decode( token, SECRET_KEY, algorithms=['HS256'], options={'verify_exp': True}, # 启用exp校验 issuer='your-issuer-name', # 校验签发者 audience='your-audience' # 校验受众 ) user_id = payload['user_id'] except jwt.ExpiredSignatureError: # 处理Token过期 return "Token expired" except jwt.InvalidTokenError: # 处理其他无效Token return "Invalid token"

从CTFHub的靶场到真实的网络攻防,JWT的安全问题清晰地展示了“魔鬼在细节中”这一道理。一个强大的加密协议,其安全性最终取决于开发者如何实现和配置它。对于攻击者而言,理解每一种手法的原理和适用场景,能让你在渗透测试中快速定位薄弱点;对于防御者而言,遵循安全最佳实践,对JWT的整个生命周期保持敬畏,是构建稳固认证体系的基石。在实际项目中,我习惯在项目初期就将这些安全配置作为代码审查清单的一部分,从源头减少漏洞的产生。毕竟,修复一个上线后发现的认证漏洞,其成本远高于在开发阶段就将其规避。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/5 9:21:29

AI开发代理落地第一关:可信执行边界的构建与PR协作机制

1. 项目概述&#xff1a;这不是AI编程&#xff0c;而是开发者工作流的“压力测试”“Software Development With Devin: Setup And First Pull Request (Part 1)”——这个标题乍看像一篇教程&#xff0c;但实际是一次对现代软件工程协作范式的真实压力测试。我用它作为切入点&…

作者头像 李华
网站建设 2026/7/5 9:21:19

Qwen3.5-27B大模型FP8量化部署实战:显存减半+推理加速

1. 项目背景与核心价值在当下大模型推理领域&#xff0c;如何平衡计算效率与推理质量一直是开发者面临的痛点。Qwen3.5-27B作为通义千问系列的重要版本&#xff0c;其27B参数量在精度和性能之间提供了较好的平衡点。但传统FP16推理对显存的高需求&#xff08;约54GB&#xff09…

作者头像 李华
网站建设 2026/7/5 9:18:20

STM32F103三路120°相移方波发生器(Keil工程+可烧录hex)

本文还有配套的精品资源&#xff0c;点击获取 简介&#xff1a;一套开箱即用的STM32F103方波信号生成方案&#xff0c;稳定输出三路频率相同、相位严格互差120度的方波信号&#xff0c;适用于电机驱动、逆变器仿真、三相测试等场景。工程基于标准外设库&#xff0c;使用TIM定…

作者头像 李华
网站建设 2026/7/5 9:17:58

Codex代码生成模型:从环境配置到项目实战的完整指南

&#x1f680; 30款热门AI模型一站整合&#xff0c;DeepSeek/GLM/Qwen 随心用&#xff0c;限时 5 折。 &#x1f449; 点击领海量免费额度 这类工具最值得先看的不是功能列表&#xff0c;而是能不能在你的开发环境里稳定跑起来&#xff0c;以及它到底能帮你解决什么具体问题…

作者头像 李华
网站建设 2026/7/5 9:06:25

DownKyi高效视频下载解决方案:轻松获取B站8K超高清内容

DownKyi高效视频下载解决方案&#xff1a;轻松获取B站8K超高清内容 【免费下载链接】downkyi 哔哩下载姬downkyi&#xff0c;哔哩哔哩网站视频下载工具&#xff0c;支持批量下载&#xff0c;支持8K、HDR、杜比视界&#xff0c;提供工具箱&#xff08;音视频提取、去水印等&…

作者头像 李华
网站建设 2026/7/5 9:04:13

AI大模型系统化学习路线与实践指南

1. 项目概述&#xff1a;为什么需要完整的AI大模型学习路线&#xff1f;三年前我刚接触Transformer架构时&#xff0c;曾花两个月时间在技术论坛零散收集资料&#xff0c;结果发现不同教程使用的框架版本冲突、数学符号体系不统一&#xff0c;甚至同一概念在不同文章中有完全相…

作者头像 李华