JWT?我一直都是這麼理解的......

邪惡的咖啡發表於2020-09-02

剛才看了learnku的另一篇文章:Laravel專案被入侵了,請問該如何應對和解決呢?,題主懷疑是系統的Token洩露導致的,JWT版本號是"tymon/jwt-auth": "^1.0",然後我去本地看了看我的依賴,發現和題主的元件和版本一樣。

於是我的擔憂來了……所以!無論如何要避免此類事情發生!

JWT組成

眾所周知,JWT是由headerpayloadsignature三者通過.拼接生成的。

JWT?我一直都是這麼理解的......
如圖所示

  • 紅色部分代表 header,主要存放JWT的加密方式等核心,由base64加密形成。
  • 紫色部分代表 payload,主要存放使用者態資訊,JWT過期時間等,由base64加密形成。
  • 藍色部分代表 signature,這個是根據header+payload的拼接再加上secret經過某種方式加密形成的(核心)。

JWT生成

本著學習的心態瞭解一下PHP如何生成JWT,一是重新瞭解一下JWT,二是想從原理上分析JWT可能存在的問題。

// 現在我有一個已生成的JWT字串
$token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c';

// 解析$token取出header
$header = '{"alg": "HS256", "typ": "JWT"}'
// 解析$token取出payload
$payload = '{"sub": "1234567890","name": "John Doe","iat": 1516239022}'

好了,JWT中前兩個已經被base64解析出來了,前兩個由於是base64方式加密,相當於明文傳輸,所以大家不要將敏感資訊放到裡面去,不然很容易被黑客抓包攔截到,從而獲取或修改使用者的敏感資訊。
那麼signature(JWT的核心校驗)是怎麼生成的呢?帶著疑問我去了一趟jwt.io

JWT?我一直都是這麼理解的......

發現生成規則後,自己動手豐衣足食……

然後我拿著剛才生成的headerpayload開啟了線上金鑰生成,假設我的金鑰為:your-256-bit-secret,按照理論來說應該生成出來的值為:SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c以對應jwt.iosignature的值。

這裡有一個大坑

JWT?我一直都是這麼理解的......

我生成了個什麼東西!!!!
然後經過一番周折發現無論如何生成的都是小寫英文加數字的組合……不符合邏輯啊

實在不行了,我去下載了"thans/tp-jwt-auth": "^1.1"的compser包,看看別人怎麼生成的。

不要問我為什麼選這個包,我隨便找的。。。

JWT?我一直都是這麼理解的......

JWT?我一直都是這麼理解的......
翻閱良久,找到生成signature的核心程式碼:hash_hmac,從沒用過這個函式,然後在官方文件分析了一下第四個引數:

  • true輸出原始二進位制資料
  • false輸出小寫 16 進位制字串。

然後煥然大悟,知道為什麼我在線上金鑰生成生成的資料對不上了。然後繼續向下走,發現生成原始二進位制資料也對不上,沒關係繼續看原始碼,然後發現問題。

JWT?我一直都是這麼理解的......

加密之後再次生成,發現還是對不上……
對比之後發現這裡有一個小坑:

  • 應該生成:SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
  • 實際生成:SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV/adQssw5c

經過翻閱原始碼發現,此base64並非原生base64,話不多說上圖,刪掉了等號,替換了加號和斜槓,不知道為什麼這麼做,莫非是是RFC規範這麼做的?。
JWT?我一直都是這麼理解的......
好了,這下就完全沒問題了,拿到jwt.io校驗一下,嗯通過了,不錯。

總結

一直都在用JWT做介面授權,只是對JWT原理略有耳聞,還沒有這麼深度的分析過,經過這次對JWT的瞭解,發現最敏感的地方就在SECRET。如果SECRET沒有洩露的話理應來說不會造成Token的安全風險,逆向的話更是無稽之談。所以至於題主Token洩露是什麼原因,排除伺服器掛馬、使用者裝置中毒、商業惡性競爭的話,我也沒分析出來。不過大家在產品上線後一定要重新生成SECRET,防止SECRET洩露。今天也算沒白活,又Get到一個知識點。:laughing:

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章