前几天做了一个登陆页面的绕过,由于认证返回的token是JWT的格式,于是花了一些时间看了看有关于JWT的东西。
# 关于JWT
JWT的全称为Json Web Token。它遵循JOSN格式,与传统的cookie session的认证方式不同,服务器使用它的好处是只需要保存秘钥信息,通过加密算法验证token即可,减小了保存用户信息的资源开销。 jwt可以分成三部分,header.payload.signature
## header部分
通常它会长成这个样子
其中alg字段指定了token加密的算法,常见的有HAMC算法、RSA算法。 typ声明类型。
## payload部分
通常会长成这样子
会有很多类似的字段,比如用户名,签发时间(iat),过期时间(exp)类似的信息。
## signature部分
这部分主要是用来保证token的完整性。 他的组成也不难,比如这样:signature=HAMC-SHA256(base64UrlEncode(header) '.' base64UrlEncode(payload),secret_key) 完整的token生成可以使用python的pyjwt库来完成,如果你要修改jwt的一部分内容可以考虑使用https://jwt.io/
# 攻击手法 ## 针对加密方式
首先可以试试,修改alg字段为None即可,类似这样
那么相应的,你JWT的第三部分也就不需要了,顺便一提,如果对方加入了对None字段的过滤的话,有时替换大小写可以绕过 第二种方法把RSA加密修改为HMAC也不错,因为它是对称加密的,所以在部分情况下好使。 比如:将第一个字段修改成这样
一般情况下都是秘钥签名,公钥用来验证。虽然无法获取到秘钥,但是公钥往往是有办法获取到。此时便可以把加密方式从RS256修改为HS256,然后把公钥用来签名发给服务器,然后服务器就会拿私钥进行解密,计划通。
## 爆破秘钥
爆破可以使用github上的工具c-jwt-cracker来完成,但是局限性很大。 首先秘钥不能太复杂,其次还需要一段已知的签过名的token。 基本打比赛偶尔能遇到,实战歇菜。
## 修改kid
kid(key ID)是JWT的header部分的可选参数,作用是用来指定加密算法秘钥。 大概长这个样子
由于这部分可以用户输入,在极少数情况下也会有用。 比如说,掌握了某一个老秘钥,但是服务器会定期更新秘钥,如果老秘钥没有删除,就可以在这里指定加密秘钥为老秘钥。 再比如说,如果过滤不严,一些注入之类的骚操作,但是局限性很大。
## 信息泄露
因为jwt简单来说就是base64encode了一段json,所以一些JWT令牌的中间部分会有一些敏感信息。 PS:最后给大家看一段代码
如果每天都是爱,内存早晚要溢出。与诸君共勉[:doge]