从 Token 到后台:JWT 漏洞利用实战全景
学习自神农安全课程
一篇写给红队与渗透测试工程师的 JWT 攻防地图。
配图般的清晰结构、可复用的测试流程、以及把门焊死的防御清单。
引言:一枚令牌里的"信任"
现代系统的身份认证,越来越像一场关于"信任"的魔术。
你登录一次,服务端递给你一枚小小的字符串——eyJxxxx.yyyy.zzzz。此后你每一次点击、每一次请求,都把这枚字符串拍在桌上,服务端扫一眼就点头放行。这枚字符串,就是 JWT(JSON Web Token)。
它的设计初衷很优雅:无状态、可携带、自包含。但也正因为它"自包含",信任被压缩进了签名里。一旦签名可以被伪造、绕过或根本不被检查,那枚令牌就不再是通行证,而是一把谁都能配的万能钥匙。
这些年我在授权渗透和攻防演练里,反复撞见同一类故事:一个看似普通的 JWT,最后撬开了后台、越权了他人账号、甚至直接接管了整个配置中心。本文把这类漏洞拆成"三类攻击 + 一个真实战场 + 一套方法论",希望读完你也能在下次测试里,快速认出那枚有问题的令牌。
一、解剖 JWT:三段式与信任模型
JWT 由两段句点切分为三部分:
Header.Payload.Signature
- Header:声明算法
alg与类型typ,Base64Url 编码; - Payload:用户身份、角色、过期时间等业务声明,Base64Url 编码;
- Signature:对前两段用密钥(或私钥)计算出的签名。
这里有一个必须刻进肌肉记忆的认知:Header 和 Payload 只是编码,不是加密。任何人拿去 jwt.io 一贴,内容一览无余。JWT 的全部安全,都压在最后那段 Signature 上——只要签名有效,服务端就无条件相信 Payload 里写的"我是 admin"。
所以,所有 JWT 漏洞的尽头都是一句话:让服务端接受一个它本不该接受的签名。实现路径只有三条:密钥失守、算法被玩坏、服务端自己不验。
二、第一类:密钥失守
JWT 的签名密钥一旦落入攻击者之手,整个信任体系就崩了——你能用任意身份重新签名,服务端照单全收。密钥"失守"有三种姿势。
2.1 密钥过弱,一爆就开
最经典的靶场 JWT_Cracking(authlab.digi.ninja)就是这种。拿到令牌后,用 jwt_tool 或 CrackJWT 跑字典,往往几十秒就能把弱密钥揪出来。某个环境里密钥干脆就是 hello——拿到它,立刻伪造一个 test1234 用户、角色 admin 的新令牌,放包过去,服务端欣然认可。
判定标志:服务端接受你"用自己的密钥签的"令牌。这说明它根本没有把"允许的密钥"写死,等价于密钥已破。
2.2 密钥泄露,明晃晃摆着
另一类靶场 Leaky_JWT 更直白:JWT 的密钥本身以某种可识别的形式出现。讲义里那个密钥是 MD5:2ac9cb7dc02b3c0083eb70898e549b63,丢进彩虹表一解就是 Password1,顺手登录。这类题的本质不是"破签名",而是"密钥根本没藏好"——可能来自前端、源码、.env、甚至报错回显。
2.3 框架默认密钥
这是生产环境里最该警惕的。许多组件出厂带着固定默认密钥,部署时没人改,于是全网同款。比如 Nacos 的 token.secret.key,默认就是一长串 SecretKey0123...——这个我们留到第五节当真实战场来讲。
三、第二类:算法被玩坏
即使密钥没泄露,算法字段 alg 本身也能成为突破口。
3.1 none 攻击:把签名删了
none 算法表示"不签名"。如果服务端错误地接受了 alg=none 的令牌,攻击者把 Payload 里改成 administrator,去掉签名段,直接就能以管理员身份过关。PortSwigger 的 flawed-signature-verification 靶场就是典型:直接改 none 被拒,但用 JWT Editor 插件的 none 攻击(自动生成大小写等多种变体)一打就中——因为服务端对 alg 的白名单校验存在缺陷。
3.2 算法混淆:拿公钥当密钥
更隐蔽的是算法混淆。想像服务端原本用 RS256(非对称,公钥验签)。攻击者的诡计是:把 alg 改成 HS256(对称),然后用服务端公开的公钥当作 HMAC 的密钥去签名。不少旧版 JWT 库会"客户端说啥算法就照做",于是公钥(本应只能验签)被当成对称密钥,签名竟然通过。
实战提示:当 none 被拒、返回
{"error":"alg not allowed"}时,别急着放弃——换 PS256→HS256 这类算法混淆向量往往能续上。
四、第三类:服务端睁一只眼
最离谱也最常见的一类:服务端压根没验证签名,或者验证逻辑写错了。
PortSwigger 的 unverified-signature 靶场:用 wiener:peter 登录后,要访问 /admin 必须伪装成 administrator。把 Cookie 里的 JWT 解出来,改用户为 administrator、算法选 none,放包——直接未授权进了 /admin。这里服务端只解析了 Payload,压根没核对签名是否合法。这种"只解析不校验"的锅,在不少自研鉴权中间件里都能见到。
五、真实战场:Nacos 默认密钥(QVD-2023-6271)
讲完原理,看一个真正能"接管系统"的案例。
资产发现:用 FOFA 一句 app="nacos" && port="8848",就能拉出一批 Nacos 配置中心。其中相当一部分还留着出厂默认密钥 token.secret.key。
漏洞本质(QVD-2023-6271):Nacos 的默认密钥写在 conf/application.properties 里,值就是:
SecretKey012345678901234567890123456789012345678901234567890123456789
攻击者拿它当签名密钥,伪造一个 sub=nacos 的 JWT,就能以平台身份直接进入后台。
利用链:
-
用 NacosExploitGUI 之类工具扫出该默认配置漏洞;
-
在 jwt.io 用默认 key 构造令牌,Payload 形如:
{ "sub": "nacos", "exp": 1721781819 }exp是 Unix 时间戳,必须比系统当前时间晚(一般改成明天)。 -
把构造好的令牌塞进登录请求包替换掉原值;
-
借助 jwt.io 重新登录抓包、改返回包、放包——直接进入网站后台。
进了后台意味着什么?Nacos 是配置中心,往往连着大量服务的账号口令与数据库连接串。配合 Derby SQL 注入、Yaml/Hessian 反序列化等链,进一步拿下 RCE 并不罕见。这也是为什么默认密钥这种"低级问题",危害却极高。
顺手记两个好用的综合利用工具:NacosExploitGUI v4.0(极核 GetShell, https://get-shell.com/7806.html )与 h0ny/NacosExploit( https://github.com/h0ny/NacosExploit )。
六、红队方法论:一个可复用的 JWT 测试流程
把前面所有案例压成一条流水线,下次遇到 JWT 直接照走:
- 抓包养成习惯:测试小程序/Web 时全程开着 BurpSuite,重点翻历史数据包——JWT、内部接口、调试字段往往只在历史包里露脸。配合 HAE 插件高亮,效率翻倍。
- 先解码,再动手:把任意 JWT 贴进 jwt.io / 无影,看 Payload 有哪些声明、服务端可能校验哪几个字段(role?user_key?username?)。
- 两路并行试探:
- 跑密钥爆破(字典/弱口令),讲义实战里小程序密钥就是
123456; - 试none 算法(
jwt_tool -X a自动生成 4 种变体)。
- 跑密钥爆破(字典/弱口令),讲义实战里小程序密钥就是
- 读返回包:
401→ 签名失败,换算法混淆或继续爆密钥;200→ 已拿下;alg not allowed→ 转 PS256→HS256 算法混淆。
- 伪造并放大:爆出密钥后,在 jwt.io 改
role=admin、改exp为明天、改username为目标账号,劫持登录包替换 token,无需密码即可越权登录他人。 - 资产级扫:对 Nacos 等组件,用 FOFA 测绘 + 默认密钥批量验证,优先处理默认配置类高危。
七、写在最后:怎么把门焊死
攻防一体。给开发和安全负责人的加固清单,三条主线:
- 密钥:HS256 密钥 ≥ 256 bit、每环境独立、绝不沿用框架默认值(Nacos 一定改
token.secret.key);定期轮转,别把密钥写进前端/仓库/回显。 - 算法:服务端只接受一种预设算法(如 RS256),验签前显式断言
alg在白名单;生产环境禁用 none;非对称验签实现必须拒绝对称算法请求,杜绝算法混淆。 - 校验:先验签、再信 Payload;验签失败直接拒绝;同时校验
exp/iss/aud防重放越权;JWT 可被解码,敏感明文切勿入 Payload;鉴权接口加频率限制与异常告警。
JWT 本身是个好设计,问题几乎都出在"信任被草率授予"。把密钥守好、把算法锁死、把签名验实,那枚令牌就会重新变回它该有的样子——一把只有真正的主人才能配的钥匙。
参考与工具
- 在线构造/解码:https://jwt.io/
- jwt_tool:https://github.com/ticarpi/jwt_tool
- 时间戳换算:https://tool.lu/timestamp/
- NacosExploitGUI:https://get-shell.com/7806.html
- h0ny/NacosExploit:https://github.com/h0ny/NacosExploit
- 漏洞参考:QVD-2023-6271(Nacos token.secret.key 默认配置)
- 练习靶场:authlab.digi.ninja(Leaky_JWT / JWT_Cracking)、portswigger.net(JWT 系列 Lab)
免责声明:本文仅用于授权环境下的安全研究与防御加固。未经授权对他人系统实施上述技术属违法行为,责任自负。

浙公网安备 33010602011771号