JWT伪造原理详解

极客

JWT伪造原理详解:一个让我半夜惊出冷汗的安全漏洞

说实话,第一次真正搞懂JWT伪造原理的时候,我后背是真的发凉,那会儿我还在做一个后台管理系统的接口鉴权,自认为用了JWT就万事大吉了,结果被安全测试的同事一句话问懵了:“你把alg改成none试试?” 我当时心想,这还能行?结果一测,好家伙,接口直接把敏感数据吐出来了,今天咱就好好聊聊这个JWT伪造原理详解,把这事儿掰开揉碎了说清楚,免得你也踩坑。

JWT伪造原理详解

先别慌,JWT到底是个啥玩意儿?

JWT,全称JSON Web Token,说白了就是一串用点号分隔的字符串,长这样:

xxxxx.yyyyy.zzzzz

它分成三截:头部(Header)、载荷(Payload)、签名(Signature),前两截就是Base64Url编码的JSON,注意啊,是编码,不是加密! 这意味着任何人拿到这串token,随手一解码就能看到里面写了啥,所以千万别往payload里塞密码、身份证号这种要命的东西,我见过有人往里塞用户手机号的,真的是心大。

头部一般长这样:

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

这个alg字段就是今天的主角,也是JWT伪造的万恶之源,服务端拿到token后,会按照这个字段声明的算法去验证签名,问题就出在——它太信任这个字段了。

JWT伪造原理详解:三种主流攻击姿势

算法混淆攻击(最骚的一种)

这个攻击的核心逻辑是:服务端原本用RS256(非对称加密,私钥签名、公钥验签)签发token,但验签代码写得不够严谨,攻击者把header里的alg改成HS256(对称加密),然后用公钥作为HS256的密钥去重新签名。

你说离谱不离谱?公钥本来是公开的,任何人都能拿到,服务端一看alg是HS256,就傻乎乎地拿自己手里的公钥当HMAC密钥去验证,结果当然通过了,这就好比你家的锁,钥匙挂在门上,然后锁还问“你是用这把钥匙开的吗?”——是的,就是用这把开的。

空算法攻击(none algorithm)

早年很多JWT库都支持alg: none,意思就是“不需要签名”,攻击者把签名部分直接删掉,alg改成none,服务端一看,哦不需要验证签名,放行,这简直是把大门敞开还贴个“欢迎光临”。

虽然现在主流库默认都禁用了none,但总有些老系统、自己手写的验证逻辑还在裸奔,我那次被问懵,就是因为项目里用的老版本库没关这个口子。

弱密钥爆破

HS256的签名密钥如果设成secret、123456、password这种,那跟没有一样,攻击者拿个字典跑一遍,几分钟就出来了,然后拿着密钥大摇大摆地伪造任意用户的token,想改谁改谁,我见过最离谱的是密钥直接用公司名字拼音的,这不明摆着送人头嘛。

那到底怎么防?说点实在的

  • 验签时强制指定算法,别信header里的alg,白名单写死RS256就别让它变成HS256。
  • 升级JWT库,老版本该扔就扔,别舍不得。
  • 密钥给我设复杂点,随机生成32位以上,别用人类能猜到的词。
  • payload里别放敏感信息,它真的只是编码,不是加密,重要的事情说三遍。

最后唠叨两句

搞清楚JWT伪造原理详解之后,我现在写鉴权代码都条件反射地先看算法校验那块,安全这东西啊,真不是用了某个“高级”技术就高枕无忧了,细节没抠到位,分分钟翻车,希望这篇能让你少走点弯路,别像我当年那样半夜惊出一身冷汗。

有啥问题欢迎评论区聊,我看到都会回,安全路上,咱一起进步!

文章版权声明:除非注明,否则均为极客网安-咸鱼原创文章,转载或复制请以超链接形式并注明出处。

目录[+]