USB descriptor parsing bug class (syzbot USB)¶
Linux USB driver'ları, enumeration sırasında saldırganın verdiği descriptor'ları parse eder ve çoğu zaman gömülü length/index alanlarına güvenir; bozuk descriptor'lar slab-out-of-bounds ve UAF bug'ları verir — syzbot tarafından Raw Gadget + Dummy HCD aracılığıyla sürekli kazılan koca bir sınıf.
Mechanism¶
Bir USB device takıldığında, host kernel onu enumerate eder: device, configuration, interface, endpoint, BOS, HID ve class'a özgü (audio/CDC/vb.) descriptor'ları ister ve herhangi bir driver "güvenilir" olmadan önce onları parse eder. Descriptor'lar kendi kendini tanımlar — her biri bir bLength taşır ve config blob'u wTotalLength taşır — ve tarihsel olarak çoğu parsing kodu o alanlara, gerçekte alınan byte'lara karşı güvenmiştir.
Note
Bu sınıf boyunca ihlal edilen invariant: device'tan gelen bir length/index/count alanına, gerçekte aldığın buffer'a karşı asla güvenme. Gerçekte olduğundan büyük (ya da küçük) bir bLength iddia eden bir descriptor, transfer'i aşan bir wTotalLength, array'i aşan bir interface/endpoint count'u ya da gömülü bir offset ile yürünen bir class header'ı — hepsi parser'ın allocation'ı aşarak okumasına ya da free etmesine izin verir. Enumeration kimlik doğrulamasından önce çalıştığından ve bir USB device sunabilen (ya da emule edebilen) herkes tarafından erişilebilir olduğundan, yüksek değerli, düşük ayrıcalıklı bir attack surface'idir.
Warning
Fiziksel olarak (BadUSB) ya da emule edilmiş bir gadget aracılığıyla, bir saldırgan herhangi bir driver onay vermeden önce her descriptor byte'ını kontrol eder. Driver'ları otomatik bind eden bir victim'de, kötü niyetli bir kablo/stick hiçbir credential olmadan bu parser'a ulaşır.
syzbot bu yüzeyi tamamen yazılımda fuzz eder: Raw Gadget, host control request'lerine yanıt olarak keyfi (bozuk) byte'lar sağlar; Dummy HCD/UDC ise tek bir kernel içinde sanal bir device controller'ı sanal bir host controller'a bağlar — donanım yok, QEMU USB passthrough yok. GadgetFS fuzzing için uygun değildir çünkü descriptor'ları sanity-check eder; Raw Gadget bunu kasten yapmaz.
Walkthrough¶
syzkaller USB fuzzing kurulumunu etkinleştirme:
# kernel .config
CONFIG_USB_RAW_GADGET=y
CONFIG_USB_DUMMY_HCD=y
CONFIG_KCOV=y # coverage incl. background threads/IRQs
CONFIG_KASAN=y # catch the OOB/UAF
# boot
dummy_hcd.num=4
syzkaller enumeration'ı pseudo-syscall'lar aracılığıyla sürer:
syz_usb_connect—SET_CONFIGURATION'a kadar enumeration/descriptor değişimini çalıştırır ve mutate edilmiş descriptor'ları besler.syz_usb_control_io— enumeration sonrası control request'leri.syz_usb_ep_write/syz_usb_ep_read— non-control endpoint I/O'su.syz_usb_disconnect.
Machine check'in USBEmulation ve ExtraCoverage gösterdiğini doğrula ve sandbox: none ile çalıştır.
syzbot'un raporladığı temsili descriptor-parsing bug'ları (hepsi enumeration'da erişilebilir):
slab-out-of-bounds in usb_get_bos_descriptor CVE-2017-16535
slab-out-of-bounds in cdc_parse_cdc_header CVE-2017-16534
slab-out-of-bounds in usb_set_configuration CVE-2017-16531
slab-out-of-bounds read in usbhid_parse CVE-2017-16533
slab-out-of-bounds in snd_usb_create_streams CVE-2017-16529
use-after-free in snd_usb_mixer_interrupt CVE-2017-16527
Bir syzbot USB reproducer'ını yeniden oynatma
Bunlar için bir syzbot C reproducer'ı aynı pseudo-syscall'ları kullanır; bir Raw-Gadget+Dummy-HCD kernel'inde bozuk descriptor'ı sunar ve KASAN tetiklenir:
Detection¶
- Test kernel'lerini
CONFIG_KASAN=yile derle ve USB reproducer'larını çalıştır; KASAN parser'daki OOB read/write'ı ya da UAF'yi tam olarak gösterir. - Dağıtılmış sistemler için, USB authorization (
/sys/bus/usb/devices/usbN/authorized) ve enumeration sırasında beklenmedik device-class bind'lerinin denetimi.
Mitigation¶
- Upstream fix'ler, her descriptor'ı deref etmeden önce açık
bLength/wTotalLengthbounds check'leri ekler; çoğu minik tek satırlık guard'lardır. - Bilinmeyen device'ları reddetmek için
CONFIG_USB_DEFAULT_AUTHORIZATION_MODE/ USBGuard; USB port'larını kilitle / kullanılmayan class driver'larını disable et. - Genel hardening: CI'da KASAN/KFENCE ve istikrarlı syzbot akışı (~200 USB bug raporlandı) göz önüne alındığında USB stack'ini yamalı tutmak.