JWT

2017-04-03 security Web JWT

JOSE(JSON Object Signing and Encryption) 定義了一系列的 RFC 標準

目前有:

  • JSON Web Signature
  • JSON Web Encryption
  • JSON Web Key
  • JSON Web Algorithm
  • JSON Web Token

JWT (JSON Web Token) 算是集前面大成者(?)

詳細的介紹可以看這裡,這邊直接從 JWT 切入

每個 JWT 稱為一個 claim,每個 claim 組成為分別為 header.payload.signature (注意它使用 ‘.’ 來虛隔三者)

Header

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

typ 代表使用 JWT

alg 代表signature 演算法使用 HS256

Payload

{
    "iss": "",
    "sub": "", 
    "aud": "", 
    "exp": "", 
    "nbf": "", 
    "iat": "", 
    "jti": ""  
}

payload 中的 data 有明確的欄位定義

因為沒有很重要所以就不做說明

Signature

因 header 裡 alg 所標示的演算法而有所差異

Example

以上每個部份都要使用 bas64 encode (將截尾用於 padding 的 = 移除),之後使用點(dot)來做連接

這裡是 JWT.io 給出的範例

header = {"alg": "HS256", "typ": "JWT"}
pylaod = {"sub": "1234567890", "name": "John Doe", "admin", true}
signature = HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), SECRET)

上述資料處理後長相如下

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

Problem

  1. none algorithm

這裡有個有趣的地方,header 部份的 alg 是可選的,之後應該由 server 端以 alg 所標明的方式驗證

但若 alg = none, 意思為不使用任何演算法處理,但格式只要正確此 JWT 仍屬有效(validate)

此處 RFC 7519 已有標明屬於 unsecrure JWT,但實做時可能會沒注意導致 header 被竄改以後 token 可被偽造

以下為 validate 的 JWT

eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.

  1. RSA or HMAC

alg 除了 HS256 還有 RS256 等其他的選項可選,假設現在我的 server 給 client 是標明使用 RS256 的驗證方式

當 alg 為 RS256 時,token 使用 private key 來簽發,但是 server 驗證的時候使用 public key 來驗證

如果將 public key 釋出自己保留 private key 的話,則只有你可以簽發 token,其他人則可以利用 public key 來驗證

這個 token 是否由你所簽發的,在實做的時候可能看起來像這樣

verify(token,verification_key)

當 server 使用 HMAC signature 時 verification_key ,function 可能會長這樣

verify(client_token, server_HMACSecretKey)

當 server 使用非對稱式演算法時,verification_key 會成為 public key,function 驗證可能長這樣

verify(client_token, serverRSAPublicKey)

因此若 header alg 從 RS256 被竄改成 HS256 則 server 會將 public key 認為是一個 HMAC secret key

問題來了 public key 是大家都可以知道的,所以 token 在這種情況下可以被 server 正確的驗證

因此 token 就可以任意偽造,視 token 的用途所造成的傷害不一。

可以在 JWT.io 了解各個語言函式庫的支援程度及安全的版本。

Reference