Aller au contenu principal

10. Security Considerations (Considérations de sécurité)

Les implémenteurs d'UTF-8 doivent être conscients de plusieurs problèmes de sécurité. Beaucoup de ces problèmes découlent de certains types de séquences malformées pouvant être créées pour éluder les vérifications de sécurité ou causer d'autres dommages.

Séquences invalides (Invalid Sequences)

Une séquence d'octets UTF-8 peut (MAY) être invalide car :

  1. Elle contient des octets interdits
  2. Elle ne peut pas compléter une séquence valide
  3. Elle code un trop grand nombre ou un numéro de caractère réservé
  4. Elle est trop longue ou
  5. Elle n'est pas codée dans la forme la plus courte possible

Forme la plus courte (Shortest Form)

L'exigence de la « forme la plus courte » est particulièrement importante pour la sécurité, comme expliqué ci-dessous.

Exigences de traitement (Processing Requirements)

Les séquences d'octets invalides ne devraient pas (SHOULD NOT) être interprétées comme des caractères ; par exemple, un interpréteur de type décalage/réduction (shift-in/shift-out) ne devrait pas (SHOULD NOT) commencer à interpréter des octets selon un schéma différent au milieu d'une séquence d'octets UTF-8.

Réaction aux séquences invalides

Une séquence invalide devrait (SHOULD) soit :

  1. Être complètement écartée, ou
  2. Être remplacée par un caractère de remplacement (tel que U+FFFD REPLACEMENT CHARACTER), selon le contexte

Pour préserver les invariants dans des documents statiques, en particulier (tels que les documents signés numériquement), il peut être nécessaire que de telles séquences soient laissées en place ; dans ce cas, leur présence doit être signalée à l'implémenteur.

Détection au niveau octet

La vérification de la forme la plus courte devrait (SHOULD) être effectuée sur les séquences UTF-8 au niveau octet (comme décrit dans la syntaxe ci-dessus), et non en :

  • Convertissant d'abord UTF-8 en caractères UCS puis en vérifiant les valeurs pour la validité
  • En vérifiant les séquences d'octets uniquement pour l'invalidité de forme

Attaques par codage non minimal (Non-Shortest Form Attacks)

Le problème

Une observation importante qui sous-tend de nombreuses vulnérabilités de sécurité avec UTF-8 est qu'un nombre quelconque de formes plus longues (et invalides) que la forme la plus courte peut être créé (en particulier pour les caractères ASCII) qui :

  • Codent le même caractère, mais
  • Diffèrent du point de vue octet

Vecteur d'attaque

Une séquence de caractères particulière, contenant un caractère Unicode de valeur faible (tel que « / »), peut être critique dans un contexte de sécurité (par exemple, comme un séparateur de nom de chemin).

Attention : Une séquence octet-par-octet invalide, qui coderait quand même le même numéro de caractère, peut échapper aux détections lors d'analyses de chaînes naïves, puis être interprétée correctement dans des opérations ultérieures, déclenchant ainsi une vulnérabilité.

Exemples d'attaques

Exemple 1 : Séquence trop longue

Caractère : '/' (barre oblique)
Unicode : U+002F

Forme correcte :
UTF-8 : 2F (1 octet)

Formes trop longues (INVALIDES) :
C0 AF (2 octets)
E0 80 AF (3 octets)
F0 80 80 AF (4 octets)

Danger : Une vérification de sécurité pourrait chercher 2F, mais un décodeur défectueux pourrait accepter C0 AF, permettant une attaque de traversée de chemin.

Exemple 2 : Attaque XSS

Caractère : '<' (moins-que)
Unicode : U+003C

Forme correcte :
UTF-8 : 3C (1 octet)

Forme trop longue (INVALIDE) :
C0 BC (2 octets)

Danger : Contourner les filtres anti-XSS qui ne recherchent que 3C.

Paires de substitution (Surrogate Pairs)

Le problème

De même, l'utilisation de séquences d'octets UTF-8 qui codent des numéros de caractères dans la plage de paires de substitution n'est pas valide, mais elle peut être générée par une implémentation simple qui convertit des données UTF-16 en UTF-8 par une traduction octet par octet.

Vecteur d'attaque

Encore une fois, une telle séquence invalide peut échapper à une vérification de sécurité, puis être interprétée correctement plus tard, déclenchant des problèmes.

Exemple

Caractère : '𣎴' (caractère chinois rare)
Unicode : U+233B4

En UTF-16 (paires de substitution) :
D84C DF34

Codage INVALIDE en UTF-8 (CESU-8) :
ED A1 8C ED BE B4

Codage CORRECT en UTF-8 :
F0 A3 8E B4

Danger : Certains systèmes peuvent accepter la séquence invalide de 6 octets, créant des incohérences.

Formes de normalisation Unicode (Unicode Normalization Forms)

Le problème

Enfin, de nombreux numéros de caractères ont une relation d'« équivalence de canonique » ou de « compatibilité » avec d'autres numéros de caractères. Lorsque deux séquences de caractères sont en relation d'équivalence, elles ont (au moins dans certains contextes) le même sens.

Implications de sécurité

Il ne peut pas être supposé que deux séquences, même si elles sont codées de manière identique en UTF-8, mais qui ne sont pas identiques octet-par-octet, ne seront pas traitées comme équivalentes par un récepteur, surtout si la normalisation est effectuée (voir [UTR-15] pour plus d'informations sur la normalisation Unicode).

Exemple

Caractère composé : 'é' (e accent aigu)
Unicode : U+00E9
UTF-8 : C3 A9

Forme décomposée : 'é' (e + accent combinant)
Unicode : U+0065 U+0301
UTF-8 : 65 CC 81

Rendu : é = é (identiques visuellement)
Octets : C3 A9 ≠ 65 CC 81 (différents)

Danger : Des vérifications de sécurité basées sur des comparaisons d'octets bruts peuvent échouer.

Recommandations de sécurité (Security Recommendations)

✅ 1. Validation stricte

Toujours valider que les séquences UTF-8 sont :

  • Dans la forme la plus courte
  • Dans la plage de caractères valide (≤ U+10FFFF)
  • Ne codent pas de paires de substitution (U+D800-U+DFFF)

✅ 2. Rejet des séquences invalides

Rejeter immédiatement toute séquence invalide. Ne pas tenter de « réparer » ou de « deviner » l'intention.

✅ 3. Normalisation Unicode

Normaliser les chaînes avant les comparaisons de sécurité. Utiliser les formes NFC ou NFD de manière cohérente.

✅ 4. Analyse au niveau octet

Valider les séquences UTF-8 au niveau octet avant toute conversion en caractères UCS.

✅ 5. Éviter les conversions multiples

Minimiser les conversions aller-retour entre différents codages pour réduire les risques d'erreur.

✅ 6. Documentation

Documenter clairement le comportement de votre implémentation lors de la rencontre de séquences invalides.


Liens connexes