
Análisis técnico de CVE-2026-52885: una condición de carrera TOCTOU en Notepad++ v8.9.6.2 que permite ejecución arbitraria de comandos mediante un bypass de integridad HMAC. Incluye la causa raíz, escenario de ataque, PoC y análisis de parche.
Notepad++ v8.9.6.2 — Ejecución de Comandos de Usuario Controlados por Atacante mediante Condición de Carrera HMAC
| GHSA | GHSA-qm4c-qg8p-qfcr |
| CVE | CVE-2026-52885 |
| Severidad | Alta |
| Afectado | v8.9.6.2 |
| Corregido | v8.9.6.4 |
| Commit de parche | 4f7563c |
| Archivo afectado | PowerEditor/src/NppCommands.cpp :4328–4359 |
| Plataforma | Windows 11 Pro x64 |
| Privilegio requerido | Usuario estándar (acceso de escritura a shortcuts.xml) |
| Investigador | v3s9er |
| Divulgado | 2026-06-05 |
Notepad++ v8.9.6.2 introdujo una verificación de integridad HMAC-SHA256 en shortcuts.xml para prevenir la inyección de entradas UserCommand arbitrarias.
La verificación tiene una falla TOCTOU: el HMAC se verifica contra el archivo en disco en el momento del disparo, pero el comando que se ejecuta se lee del vector _userCommands en memoria cargado al inicio. Estas dos fuentes nunca se vuelven a sincronizar.
Un atacante que pueda escribir en shortcuts.xml puede plantar un comando malicioso antes del inicio, dejar que Notepad++ lo cargue en memoria, restaurar el archivo legítimo en disco y luego disparar el comando. La verificación HMAC pasa (disco limpio), pero la carga maliciosa se ejecuta (memoria obsoleta).
El mecanismo de integridad valida el shortcuts.xml actual en disco, mientras que la ejecución del comando utiliza una representación en memoria cargada previamente. Debido a que las dos fuentes de datos son independientes, un atacante puede alterar el archivo antes del inicio, permitir que se analice en memoria, luego restaurar el archivo original antes de la ejecución del comando — provocando que la verificación HMAC pase mientras la carga maliciosa se ejecuta.
NppCommands.cpp líneas 4328–4359:
// TIEMPO DE VERIFICACIÓN — lee el archivo en disco
std::string currentHMAC = computeHMAC(
getMachineGUID(),
getFileContent(nppParams.getShortcutsPath().c_str())
);
if (currentHMAC != nppGUI._shortcutsXmlHmacInConfig) { return; }
// validado contra DISCO
// TIEMPO DE USO — lee el vector en memoria (cargado al inicio, nunca actualizado)
int i = id - ID_USER_CMD;
const vector<UserCommand>& cmds = nppParams.getUserCommandList();
UserCommand ucmd = cmds[i];
Command cmd(string2wstring(ucmd.getCmd(), CP_UTF8));
cmd.run(_pPublicInterface->getHSelf()); // ejecuta carga desde MEMORIA
| Operación | Fuente | Momento |
|---|---|---|
| VERIFICACIÓN (HMAC) | Archivo en disco | En el momento del disparo |
| USO (ejecución) | Vector en memoria | Cargado al inicio |
| VENTANA | Controlada por atacante | Inicio → Disparo |
Precondición: acceso de escritura a shortcuts.xml
notepad++.exe%AppData%\Notepad++\Pasos:
shortcuts.xml en disco con una versión maliciosa (cmd = calc.exe)_userCommands se puebla desde el archivo maliciososhortcuts.xml legítimo en disco — ahora HMAC coincide con config.xmlWM_COMMAND(21000) (ID_USER_CMD+0) o presionar Ctrl+Alt+P_userCommands[0] desde memoria → calc.exe se ejecutaResultado: ejecución de comandos controlados por atacante bajo los privilegios del usuario actual. Sin administrador, sin UAC, sin advertencia al usuario.
Ver poc_8962_toctou.ps1.
Requisitos:
doLocalConf.xml presente en el directorio de Notepad++ (modo portátil)config.xml con un HMAC válido para el shortcuts.xml legítimo.\poc_8962_toctou.ps1 -NppPath "C:\ruta\a\notepad++.exe"
Verificado: calc.exe generado (PID 35932), el disco muestra shortcuts.xml legítimo durante todo el proceso.
La corrección (commit 4f7563c) mueve la validación HMAC al inicio, junto con el análisis inicial del archivo. La verificación y el uso ahora operan sobre el mismo objeto al mismo tiempo, eliminando la ventana TOCTOU.
| v8.9.6.2 (vulnerable) | v8.9.6.4 (corregido) | |
|---|---|---|
| Verificación HMAC | En el momento del disparo, relee el disco | Al inicio, mismos bytes que el análisis |
| Fuente del comando | Memoria cargada al inicio | Memoria validada al inicio |
| Ventana TOCTOU |
| Tiempo | Evento | Estado |
|---|
| T+0.0s | Atacante escribe shortcuts.xml MALICIOSO | disco=MALICIOSO |
| T+0.0s | Atacante inicia Notepad++ | disco=MALICIOSO |
| T+0.1s | Notepad++ lee shortcuts.xml → _userCommands[0]="calc.exe" | mem=MALICIOSO |
| T+4.2s | Notepad++ completamente cargado | mem=MALICIOSO |
| T+4.2s | Atacante restaura shortcuts.xml LEGÍTIMO | disco=LEGÍTIMO / mem=MAL |
| T+4.7s | Atacante envía WM_COMMAND(21000) | |
| T+4.7s | Verificación HMAC: lee archivo LEGÍTIMO desde disco → PASA | VERIFICACIÓN OK |
| T+4.7s | Ejecución: lee _userCommands[0] desde MEMORIA → calc.exe | EXPLOTACIÓN |
| T+4.7s | calc.exe generado (PID 35932) | CONFIRMADO |
| Tipo | Ejecución de Comandos Arbitrarios |
| Requiere Admin | No |
| Solicitud UAC | No |
| Detectabilidad | Baja — el disco muestra el archivo legítimo durante todo el proceso; la carga está solo en memoria |
| CVSS (est.) | AV:L / AC:H / PR:L / UI:N / S:U / C:H / I:H / A:H |
| Inicio → Disparo |
| Eliminada |