FlawOpen

flawopen.com/Teardowns/cve-2026-49878-android-wpa-supplicant-oob-write

● CVE-2026-49878 · CVSS 7.2 · Haute
Recherche · FlawOpen

CVE-2026-49878 : écriture hors limites dans le Wi-Fi Android

Le bulletin Android d’octobre 2026 classe comme élevée cette faille RCE du Wi-Fi. AOSP a corrigé deux tableaux int alloués en octets plutôt qu’en éléments. La fiche indique que des privilèges système sont requis.

💡 Explication en Langage Simple (ELI5)

Imaginez une étagère prévue pour une boîte par article, mais où l’on ne réserve qu’un centimètre par boîte. Les boîtes dépassent de l’espace prévu. Dans CVE-2026-49878, wpa_supplicant comptait des octets avec le nombre d’entiers, puis écrivait des entiers complets. Le correctif Google réserve chaque élément à sa taille réelle.

Concepts Clés et Termes

wpa_supplicant
Composant Wi-Fi Android qui gère l’authentification sans fil et les interactions 802.11.
Réponse SCS
Trame d’action de réponse du Stream Classification Service. Le gestionnaire ne la traite que si une requête est en attente et que le jeton de dialogue correspond.
Écriture hors limites (CWE-787)
Écriture au-delà de la mémoire réservée. Ici, l’allocation compte des octets alors que le code indexe des éléments int.
os_zalloc / os_calloc
Fonctions d’allocation de wpa_supplicant. Le correctif passe le nombre et la taille des éléments pour réserver le tableau complet.
Niveau de correctif de sécurité Android (SPL)
Date identifiant le niveau de mise à jour installé. Google indique que 2026-10-01 ou ultérieur corrige le bulletin ; le fabricant gère le déploiement.

Correspondances de référentiels

  • Référence CWE pour la faiblesse décrite dans ce guide : CWE-787

Analyse de Cause Racine

Dans wpas_handle_robust_av_scs_recv_action, scs_resp[0] et [1] sont des tableaux int *. Avant le correctif, os_zalloc(num_active_scs) ne réservait que ce nombre d’octets. Le code écrit des identifiants et états entiers par indice ; il faut donc num_active_scs * sizeof(int) octets. Les contrôles de requête en attente, de jeton correspondant, de nombre et de longueur de trame bornent les entrées, mais ne corrigent pas l’unité d’allocation. Le correctif AOSP remplace les deux appels par os_calloc(num_active_scs, sizeof(int)). Cette écriture hors limites ne permet pas à elle seule de conclure à une exécution de code contrôlée par l’attaquant.

Déroulement de l'Attaque Étape par Étape

Étape 1

Une trame de réponse est transmise

Le chemin Wi-Fi dirige Robust AV SCS Response vers le gestionnaire. La voie est réseau, mais les sources ne prouvent pas qu’un émetteur non authentifié puisse satisfaire toutes les préconditions.

Étape 2

État et limites sont vérifiés

Le gestionnaire exige une requête en attente et un jeton correspondant, puis valide le nombre. Le vecteur CISA-ADP de NVD indique AV:N/AC:L/PR:H/UI:N ; conserver l’exigence de privilèges élevés.

Étape 3

Les entiers dépassent l’allocation en octets

L’ancien code réserve un octet par entrée et écrit des valeurs int. Borner le nombre n’augmente pas la taille allouée.

Étape 4

Le correctif d’octobre corrige l’allocation

Le changement Google réserve num_active_scs éléments de sizeof(int) pour les deux tableaux. Ne pas inventer de charge utile ni prétendre que le diff démontre une exécution arbitraire.

Code Source : Vulnérable vs Sécurisé

Le diff est la modification publiée par AOSP dans le commit d131540379d631d7dcb09b0169e4462bc65abcca, pas du pseudocode reconstitué. os_zalloc(n) utilise n comme taille en octets ; os_calloc(count, size) réserve et met à zéro le nombre demandé d’éléments. La correction répare les deux tableaux et conserve le nettoyage existant en cas d’échec d’allocation.

IMPLÉMENTATION VULNÉRABLE
/* AOSP avant correction : num_active_scs représente un nombre d’éléments,
 * mais os_zalloc le reçoit comme un nombre d’octets. */
scs_resp[0] = (int *) os_zalloc(num_active_scs);
if (!scs_resp[0])
    return;

scs_resp[1] = (int *) os_zalloc(num_active_scs);
if (!scs_resp[1]) {
    os_free(scs_resp[0]);
    return;
}
PATCH SÉCURISÉ ET ROBUSTE
/* Correction AOSP : allouer un int complet pour chaque entrée. */
scs_resp[0] = os_calloc(num_active_scs, sizeof(int));
if (!scs_resp[0])
    return;

scs_resp[1] = os_calloc(num_active_scs, sizeof(int));
if (!scs_resp[1]) {
    os_free(scs_resp[0]);
    return;
}

Liste de Contrôle de Sécurité pour l'Ingénierie

Sources