JWT是用作兩個(gè)服務(wù)之間傳遞聲明的簡潔結(jié)構(gòu)小压。他們通常是json對(duì)象弄息,并且可以用于加密(或不加密)消息認(rèn)證碼(MAC)猬膨,通過簽名的方式來保護(hù)底層信息的完整性。JWT結(jié)構(gòu)來源自RFC7519標(biāo)準(zhǔn)答毫。 一個(gè)JSON Web Token(JWT)包含3個(gè)部分: encoded Header(編碼頭)褥民,encoded Payload(編碼信息主體),Signature(簽名) 洗搂。
header包含的信息消返,定義了token令牌的類型,還有payload的加密算法耘拇。
payload包含了路由和服務(wù)的claim 鍵值對(duì)撵颊,這里可以存放大量的信息。一個(gè)claim 通常定義了最終用戶的身份或者一些額外的信息惫叛,這取決于claim 的類型倡勇。例如:
Reserved Claims: 一些前置定義和一些有用的互動(dòng)信息。比如issuer (發(fā)行主體), sub (提供者), expiration time (過期時(shí)間), audience (接收者) 還有其他的信息嘉涌。
Public Claims: 在 IANA JSON Web Token Registry公開使用的或者作為URI妻熊。
Private Claims:由雙方定義并分享的一些Claims。
最后仑最,signature 是header和payload由BASE64編碼后通過密鑰加密計(jì)算生成的扔役。(關(guān)于Claims的詳細(xì)介紹見http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html#rfc.section.4)
盡管Jwt支持對(duì)稱和非對(duì)稱的加密方式,但我們將針對(duì)對(duì)稱加密HMAC SHA 256[HS256]這些加密方式展開討論词身,因?yàn)橄旅娴膯栴}會(huì)使用到它厅目。
這是在一個(gè)請(qǐng)求中有效的JWT例子番枚。下面的右圖表示JWT包含的3個(gè)部分法严,Header, Payload,還有計(jì)算生成的Signature葫笼。生成的token是由編碼后的header,payload,signature組合而成的深啤,如左圖。
認(rèn)證
JWT或許是應(yīng)用中最常用的身份認(rèn)證方式路星。認(rèn)證成功之后溯街,應(yīng)用給用戶頒發(fā)認(rèn)證token诱桂,它將成為用戶獲取所有服務(wù)資源的憑據(jù)。理論上呈昔,這個(gè)token需要被密鑰保護(hù)挥等。
分析
在這篇博客中,我們討論這樣一個(gè)案例堤尾,該案例使用了JWT的不良實(shí)現(xiàn)來作用戶的認(rèn)證和授權(quán)肝劲。
分析初始請(qǐng)求時(shí),我們可以確認(rèn)網(wǎng)站正在使用jwt做身份認(rèn)證郭宝。
接下來辞槐,在返回中,我們可以找到包含用戶配置信息的編碼token粘室,如下圖:
登陸成功后榄檬,我們可以訪問任務(wù),文檔管理還有一些普通用戶的其他的功能衔统,如下圖
到這里鹿榜,我們回想一下,分析我們收到的這個(gè)認(rèn)證token锦爵。我們使用https://jwt.io/提供的功能來驗(yàn)證不同密鑰的signature 犬缨。當(dāng)然,在大多數(shù)情況下我們使用這個(gè)方法無法得到有效的signature 棉浸。
在此關(guān)鍵時(shí)刻怀薛,我們無法組合一個(gè)有效的signature來幫助我們修改payload和生成一個(gè)有效的正確token。我們?nèi)笔籎WTS簽名的
‘secret key’迷郑。我們寫一個(gè)簡單的python腳本從一串可猜測的隨機(jī)的字符串(存在本地文件secret.txt中)來暴力破解‘secret key’枝恋,如下圖:
我們最終成功的暴力得到了用于JWT簽名的正確密鑰,如下
為了確認(rèn)這確實(shí)是個(gè)正確的token嗡害,我們檢驗(yàn)不修改payload和header生成的signature 與先前的signature 是否一致(筆者注:填寫暴力破解的secret key焚碌,檢查產(chǎn)生的signature 與先前的signature )
現(xiàn)在我們得到了正確的密鑰,我們寫一個(gè)新的token,在角色屬性中增加“admin”來發(fā)起一次新的請(qǐng)求霸妹。下圖展示的是修改了角色的JWT請(qǐng)求的頁面十电,新的token是用了上一步獲得的密鑰簽名得到的。
在服務(wù)端接收的Authorization header頭中叹螟,我們使用了上一步創(chuàng)建的token鹃骂。上一次我們的用戶是site visitor(訪問者),現(xiàn)在我們得到了更高的(管理者)權(quán)限罢绽。下圖展示的是我們用自己創(chuàng)造的token傳遞給服務(wù)器畏线。
此外,我們還訪問了管理員功能良价,比如用服務(wù)提供的token來管理用戶寝殴。
有意思的是蒿叠,對(duì)于上面提到的系統(tǒng),可以通過修改持有token的jwt的payload來模擬用戶蚣常。
結(jié)論
服務(wù)使用JWT來保護(hù)它的資源是欠妥當(dāng)?shù)氖醒省J褂貌粔虬踩模軌虮┝ζ平獾拿荑€來對(duì)JWTs簽名會(huì)造成不好的結(jié)果抵蚊。在上面的情形中魂务,只要密鑰被得到,心存不良的人可以提升它的權(quán)限來訪問服務(wù)的管理功能泌射。這對(duì)水平和垂直的權(quán)限提升同樣有效粘姜,或者簡單的枚舉用戶的IDs來模擬其他用戶。
給敏感的數(shù)據(jù)配置強(qiáng)度高的值熔酷,比如密碼和密鑰孤紧,對(duì)于保護(hù)服務(wù)和它的用戶遭到攻擊大有裨益。