Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

v2: t:utf8toUnicode drops the last hex digit of code points above U+FFFF (regression since 2.9.9)

Aperta Adatta ai principianti
#3,684 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
2/5
Tempo stimato
1-3 ore
Idoneità per principianti
78/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
apache, c
Ambito
security

Direzione di ricerca

Il bug si trova in utf8_unicode_inplace_ex() in apache2/msc_util.c, nel ramo che chiama sprintf(data, "%%u%04x", d) e poi esegue data += 6. Inizia da lì: l'avanzamento del puntatore dovrebbe seguire la lunghezza restituita da sprintf(), e bytes_left dovrebbe tenere traccia dell'input rimanente. Aggiungi un caso di sequenza a quattro byte in tests/tfn/utf8toUnicode.t. È fatto quando U+1F600 viene trasformato in %u1f600 e i casi BMP esistenti continuano a passare.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Summary

In ModSecurity v2 (2.9.9 through 2.9.15, and current v2/master), t:utf8toUnicode emits only four of the five hex digits for any code point above U+FFFF (supplementary planes: emoji, CJK extensions, mathematical alphanumerics, ...). The last digit is overwritten by whatever the function writes next, or by the terminating NUL when the character is the last one in the value.

Related to #1211 (ambiguous output of this transformation), but this is a separate, newer defect: #1211 describes the 4-digit vs. 6-digit ambiguity by design; this issue is a plain truncation introduced by the refactor in #3284 (commit 907d61ad, fix for #3129), first released in 2.9.9. libModSecurity v3 is not affected (its port still writes the digits one by one), although it shares the #1211 ambiguity.

Reproduction

Output of utf8_unicode_inplace_ex() from apache2/msc_util.c at v2.9.15, compiled standalone:

Input Output Expected
U+1F600 (f0 9f 98 80) %u1f60 %u1f600
U+1F600 followed by A %u1f60A %u1f600A
a U+1F600 U+00E5 a%u1f60%u00e5 a%u1f600%u00e5
U+20AC (e2 82 ac) %u20ac %u20ac (BMP characters are fine)
Cause
if (unicode_len > 0) {
    i += unicode_len;
    sprintf(data, "%%u%04x", d);
    data += 6;          /* "%u" + 4 digits, but d > 0xFFFF prints 5 digits */
    *changed = 1;
}

Before 907d61ad the four-byte branch wrote the digits individually, so 5-digit code points were preserved.

Two adjacent problems in the same function
  • bytes_left is initialised to input_len and never decremented, so the "check we have at least N bytes" guards compare against the total length instead of the remaining length. A truncated multibyte sequence at the end of the value reads past input_len. In practice the read stops at the NUL that terminates every v2 variable value, so it is bounded to one byte, but the guard is wrong.
  • The range check only rejects lead bytes >= 0xF5; an 0xF4 lead byte with a second byte >= 0x90 encodes U+110000 and above, which is outside Unicode, and is currently accepted.
Impact

Correctness only, as far as I can tell: the output buffer is sized at ten bytes per input byte and a 4-byte sequence writes at most eight, so nothing is written outside the allocation, and the transformed string is always a superset of the ASCII input, so I could not construct a rule bypass with it. Rules that match %uXXXXX sequences for supplementary-plane characters do not work, and the transformed value is wrong in the audit log.

Proposed fix

Advance data by the value sprintf() returns instead of a constant 6, decrement bytes_left (or compare against input_len - i), reject code points above U+10FFFF, and add a four-byte sequence to tests/tfn/utf8toUnicode.t, which currently has none. PR to follow.

Lingua principale
C++
Stelle
9.8k
Fork
1.8k
Merge medio
1g 1h
PR unite (30g)
13

Preparare l'ambiente

  • Nessun Dockerfile né file Docker Compose
  • Ha un modello di pull request
  • Nessuna guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di owasp-modsecurity/ModSecurity

Tutte le issue di owasp-modsecurity/ModSecurity

Issue simili

Altre issue su C++

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.