CTFHub題解-技能樹-Web進階-JSON Web Token【敏感信息泄露、無簽名】
題外話:emmmm,停更了辣么久......我又厚臉皮回來更新了,哈哈哈哈哈~(。・∀・)ノ゙
(一)敏感信息泄露
1.知識點
* 先來了解一下 用戶認證流程 :
(1)用戶向服務器發送用戶名和密碼。
(2)服務器驗證通過后,在當前對話(session)里面保存相關數據,比如用戶角色、登錄時間等等。
(3)服務器向用戶返回一個 session_id,寫入用戶的 Cookie。
(4)用戶隨后的每一次請求,都會通過 Cookie,將 session_id 傳回服務器。
(5)服務器收到 session_id,找到前期保存的數據,由此得知用戶的身份。
JSON Web Token (縮寫 JWT),服務器認證以后,生成一個 JSON 對象,發回給用戶。
以后,用戶與服務端通信的時候,都要發回這個 JSON 對象。
服務器完全只靠這個對象認定用戶身份。
為了防止用戶篡改數據,服務器在生成這個對象的時候,會加上簽名。
JWT 的結構 :
由三部分構成:
Header.Payload.Signature
頭部.負載.簽名
舉個栗子~
JWT大概就是這種形式:
頭部:eyJBRyI6IjNmMjhhYzg3NTA2M2JmMn0iLCJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.
負載:eyJ1c2VybmFtZSI6ImFkbWluIiwicGFzc3dvcmQiOiIxMjM0NTYiLCJGTCI6ImN0Zmh1Yns5ODMzZTE1NzQifQ.
簽名:jFf_cb3Fx3EkOwrTR4ro_a3lMAq3Rd44mfJ8Pih6DqI
它是一個很長的字符串,中間用點 . 分隔成三個部分。
Header 部分是一個 JSON 對象,描述 JWT 的元數據。
Payload 部分也是一個 JSON 對象,用來存放實際需要傳遞的數據。
Signature 部分是對前兩部分的簽名,防止數據篡改。這里需要指定一個密鑰(secret)。這個密鑰只有服務器才知道,不能泄露給用戶。然后,使用 Header 里面指定的簽名算法(默認是 HMAC SHA256)。
注意:Header 和 Payload 串型化的算法是 Base64URL。
JWT 作為一個令牌(token),有些場合可能會放到 URL(比如 api.example.com/?token=xxx)。Base64 有三個字符+、/和=,在 URL 里面有特殊含義,所以要被替換掉:=被省略、+替換成-,/替換成_ 。
JWT的特點 :
(1)JWT 默認是不加密,但也是可以加密的。
(2)JWT 不加密的情況下,不能將秘密數據寫入 JWT。
(3)JWT 不僅可以用於認證,也可以用於交換信息。有效使用 JWT,可以降低服務器查詢數據庫的次數。
(4)JWT 簽發了,在到期之前就會始終有效,因為服務器不保存 session 狀態,因此無法在使用過程中廢止某個 token,或更改 token 的權限。
(5)JWT 本身包含了認證信息,一旦泄露,任何人都可以獲得該令牌的所有權限。
(6)JWT 不應該使用 HTTP 協議明碼傳輸,要使用 HTTPS 協議傳輸。
2.題解
打開時候發現是個登錄框,先抓個包看看吧~


我們看到Response的token是這個樣子的:
eyJBRyI6IjNmMjhhYzg3NTA2M2JmMn0iLCJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwicGFzc3dvcmQiOiIxMjM0NTYiLCJGTCI6ImN0Zmh1Yns5ODMzZTE1NzQifQ.jFf_cb3Fx3EkOwrTR4ro_a3lMAq3Rd44mfJ8Pih6DqI
拿去進行 base64url 解碼:
可以用burp自帶的解碼器 Decoder :
也可以用 解碼網站: https://base64.us/#
看到解碼結果,發現了ctfhub的字樣,emmmm,只有一半........
那么另一半.........再仔細看看結果,原來在解碼結果的前半段~
拼起來就可以了~
ctfhub{9833e15743f28ac875063bf2}
(二)無簽名

1.知識點
JWT 和 Base64Url 的知識點可以參考上面一道題哦~
2.題解
Go一下看看情況:
先把 token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwicGFzc3dvcmQiOiIxMjM0NTYiLCJyb2xlIjoiZ3Vlc3QifQ.MaphZVk25q4stXxAmEgXmKCW7aUo3jDJtgv9DwahLwc; 粘下來。
直接用burp自帶的 Decoder 進行 base64url 解碼吧~
解出來的結果是這個:
{"typ":"JWT","alg":"none"}.{"username":"admin","password":"123456","role":"admin"fQ.1ªaeY6æ®,µ|@H í¥(Þ0ɶý¡Lwc
從題目提示可以知道:一些JWT庫也支持none算法,即不使用簽名算法。當alg字段為空時,后端將不執行簽名驗證。
先解碼 頭部 :
接着將 HS256算法 修改成 none 算法。
轉碼~
JWT 作為一個令牌(token),有些場合可能會放到 URL(比如 api.example.com/?token=xxx)。Base64 有三個字符+、/和=,在 URL 里面有特殊含義,所以要被替換掉:=被省略、+替換成-,/替換成_ 。
eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0=
接着解碼 負載 :
這里沒有顯示},可能是因為等號 = 省略的原因,我們可以先加上
eyJ1c2VybmFtZSI6ImFkbWluIiwicGFzc3dvcmQiOiIxMjM0NTYiLCJyb2xlIjoiYWRtaW4ifQ==
解碼出來是
{"username":"admin","password":"123456","role":"guest"}
這里將 guest 修改成 admin
轉碼~
好啦~
把 頭部 和 負載 拼起來,記得 負載 后的 . 要加上喲~
原始JWT:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwicGFzc3dvcmQiOiIxMjM0NTYiLCJyb2xlIjoiZ3Vlc3QifQ.MaphZVk25q4stXxAmEgXmKCW7aUo3jDJtgv9DwahLwc
修改 none算法 和 admin 的JWT:
eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJ1c2VybmFtZSI6ImFkbWluIiwicGFzc3dvcmQiOiIxMjM0NTYiLCJyb2xlIjoiYWRtaW4ifQ==.
然后我們把 token 替換到 Request 里面,Go一下
emmmmm.....怎么沒有flag呢?
仔細看一下跳轉的頁面,是... /index.php
那就把 Request 的這部分修改一下吧~
POST /index.php HTTP/1.1
Go一下,看到 flag 啦~
ctfhub{d888243961e7b9e90c321e37}
參考資料:
https://jwt.io/introduction/
http://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html
https://blog.csdn.net/rfrder/article/details/108619373