Skip to content

USB HID sniffing example: YubiKey OTPs

Joost van Dijk edited this page Oct 28, 2019 · 2 revisions

A USB sniffing example: capturing YubiKey OTPs.

Tools like WireShark can capture wired and wireless network traffic, but also USB data. Captured data may need to be processed to distill information. For instance, keystrokes from a USB keyboard.

wireshark

A USB keyboard is a USB HID device. A YubiKey is like a one-button USB keyboard, generating 44-character OTPs whenever the button is pressed (followed by the "enter" key).

When recording USB traffic while pushing the YubiKey button, and saving the capture in a file (ykotcp.pcapng), we can use a command-line tools like tshark to display this traffic:

$ tshark -r ykotp.pcapng | head -5
    1   0.000000        1.2.1 → host         USB 35 URB_INTERRUPT in
    2   0.005220        1.2.1 → host         USB 35 URB_INTERRUPT in
    3   0.010535        1.2.1 → host         USB 35 URB_INTERRUPT in
    4   0.015902        1.2.1 → host         USB 35 URB_INTERRUPT in
    5   0.021161        1.2.1 → host         USB 35 URB_INTERRUPT in

To extract the OTP, we may need to filter on -Y "usb.transfer_type == 0x01". The keystrokes are recorded in Leftover Capture Data (See reference), which can be displayed with a display filter, in field usb.capdata.

$ tshark -r ykotp.pcapng -Tfields -e usb.capdata  | head -5
0000060000000000
0000000000000000
0000060000000000
0000000000000000
0000060000000000

This data consist of scan codes. Note that the all-zeros scan code (0000000000000000 ) means that no character was transmitted.

As Yubikeys produce OTPs consisting of the limited set of characters (bcdefghijklnrtuv) used in modhex encoding, we can easily translate between the two using tr:

alias decode="tr '\5\6\7\10\11\12\13\14\15\16\17\21\25\27\30\31\50' 'bcdefghijklnrtuv\n'"

Refer to the table of USB scan codes to translate each code to its corresponding modhex character.

Now, we can use a simple script to retrieve the OTP:

$ tshark -r ykotp.pcapng -Tfields -e usb.capdata | cut -c5-6  | grep -v 00 | xxd -r -p | decode
ccccccbtulitjgeijciegvulruugfbuujjrujfuinfil

When validating the OTP, we can see that we are too late: it has already been validated:

replayed

See also: http://blog.joostd.nl/2014/02/21/yubikey.html

Clone this wiki locally