USB
Host-controlled bus where a device declares what it is through descriptors. The host trusts those claims, which is the whole attack surface.
USB (Universal Serial Bus) is a host-controlled bus: a device attaches, and during enumeration it tells the host what it is through a tree of descriptors before any application data flows. The host then loads a driver based purely on those self-declared claims. That trust, the host believing whatever the device says it is, is the root of every USB attack.
What it is
USB is strictly host-centric: the host polls, the device answers, devices never initiate on their own. On plug-in, the host resets the port, assigns an address, and reads descriptors in a fixed hierarchy: the device descriptor (vendor/product ID, class), one or more configuration descriptors, each grouping interface descriptors (one per function, carrying a class code), and under each interface the endpoint descriptors that define the actual data pipes.
| Element | Detail |
|---|---|
| Enumeration | host resets, addresses, and reads descriptors |
| Descriptors | device to configuration to interface to endpoint |
| Classes | HID, mass storage, CDC (serial), audio, vendor |
| Endpoints | control (EP0) plus bulk / interrupt / isochronous |
A single physical device can be composite: expose several interfaces at once (for example, a flash drive that is also a keyboard).
Why it matters
The host acts on the device's word. A gadget can present an HID keyboard interface and type commands the instant it is plugged in (BadUSB / HID injection), hide a second interface behind a benign-looking one, or feed the host malformed descriptors to trip driver parsing bugs in ring-0 code. Embedded products routinely leave a debug or DFU USB interface exposed, and mass-storage autorun paths remain a classic delivery vector.
How to work it
- Enumerate what is attached and read the full descriptor tree:
lsusb # list attached devices
lsusb -v -d 1234:5678 # full descriptors for one device
- Capture live USB traffic to understand a protocol or replay it:
sudo modprobe usbmon
# then select the usbmonX interface in Wireshark, or:
sudo cat /sys/kernel/debug/usb/usbmon/1u
- Emulate a device to test how the host reacts: a Facedancer/GreatFET, or Linux gadget mode (
libcomposite/ ConfigFS) on a Pi Zero or an OTG-capable board, lets you present arbitrary descriptors and classes. - HID injection: script keystrokes on a Rubber Ducky, a Pi Zero in HID gadget mode, or an RP2040, to run commands on any host that trusts an attached keyboard.
- Fuzz descriptors (with a tool such as umap2) to hunt for host-driver crashes on malformed or contradictory descriptor trees.
Pitfalls
- Emulation needs a UDC (USB device controller); a normal PC USB port is host-only and cannot present as a device without gadget-capable hardware.
- Screen-lock and endpoint-allowlisting mitigations mean HID injection is not guaranteed; it depends on the target's posture.
lsusb -vneeds privileges to read the full descriptor set; a truncated dump is a permissions artefact, not a device limit.- USB-C and higher-speed links add alternate modes and negotiation, but the classic descriptor-trust model still underpins the data path.