
Технический анализ CVE-2026-52885: состояние гонки TOCTOU в Notepad++ v8.9.6.2, позволяющее произвольное выполнение команд через обход целостности HMAC. Включает основную причину, сценарий атаки, PoC и анализ исправления.
| GHSA | GHSA-qm4c-qg8p-qfcr |
| CVE | CVE-2026-52885 |
| Серьёзность | Высокая |
| Затрагиваемая версия | v8.9.6.2 |
| Исправленная версия | v8.9.6.4 |
| Коммит исправления | 4f7563c |
| Затрагиваемый файл | PowerEditor/src/NppCommands.cpp :4328–4359 |
| Платформа | Windows 11 Pro x64 |
| Необходимые привилегии | Обычный пользователь (доступ на запись к shortcuts.xml) |
| Исследователь | v3s9er |
| Дата раскрытия | 2026-06-05 |
В Notepad++ v8.9.6.2 была введена проверка целостности HMAC-SHA256 для shortcuts.xml, чтобы предотвратить внедрение произвольных записей UserCommand.
Проверка содержит ошибку TOCTOU: HMAC проверяется по файлу на диске в момент вызова, но выполняемая команда читается из вектора _userCommands в памяти, загруженного при запуске. Эти два источника никогда не синхронизируются повторно.
Атакующий, имеющий возможность записывать в shortcuts.xml, может разместить вредоносную команду до запуска, позволить Notepad++ загрузить её в память, восстановить легитимный файл на диске, а затем запустить команду. Проверка HMAC проходит (диск чист), но вредоносная нагрузка выполняется (память устарела).
Механизм целостности проверяет текущий shortcuts.xml на диске, а выполнение команды использует ранее загруженное представление в памяти. Поскольку эти два источника данных независимы, атакующий может изменить файл до запуска, дать ему возможность быть разобранным в память, а затем восстановить исходный файл перед выполнением команды — в результате проверка HMAC проходит, а вредоносная нагрузка выполняется.
NppCommands.cpp строки 4328–4359:
// TIME OF CHECK — чтение файла с диска
std::string currentHMAC = computeHMAC(
getMachineGUID(),
getFileContent(nppParams.getShortcutsPath().c_str())
);
if (currentHMAC != nppGUI._shortcutsXmlHmacInConfig) { return; }
// проверка по ДИСКУ
// TIME OF USE — чтение вектора из памяти (загружен при запуске, не обновляется)
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()); // выполнение нагрузки из ПАМЯТИ
| Операция | Источник | Время |
|---|---|---|
| ПРОВЕРКА (HMAC) | Файл на диске | В момент вызова |
| ИСПОЛЬЗОВАНИЕ (выполнение) | Вектор в памяти | Загружен при запуске |
| РАЗРЫВ | Управляется атакующим | Запуск → Вызов |
Предварительное условие: доступ на запись к shortcuts.xml
notepad++.exe%AppData%\Notepad++\Шаги:
shortcuts.xml на диске вредоносной версией (cmd = calc.exe)_userCommands заполняется из вредоносного файлаshortcuts.xml на диск — HMAC теперь совпадает с config.xmlWM_COMMAND(21000) (ID_USER_CMD+0) или нажать Ctrl+Alt+P_userCommands[0] из памяти → запускается calc.exeРезультат: выполнение управляемых атакующим команд с привилегиями текущего пользователя. Без прав администратора, UAC или предупреждения пользователя.
| Время | Событие | Состояние |
|---|---|---|
| T+0.0с | Атакующий записывает ВРЕДОНОСНЫЙ shortcuts.xml | диск=ВРЕДОНОСНЫЙ |
| T+0.0с | Атакующий запускает Notepad++ | диск=ВРЕДОНОСНЫЙ |
| T+0.1с | Notepad++ читает shortcuts.xml → _userCommands[0]="calc.exe" | память=ВРЕДОНОСНЫЙ |
| T+4.2с | Notepad++ полностью загружен | память=ВРЕДОНОСНЫЙ |
| T+4.2с | Атакующий восстанавливает ЛЕГИТИМНЫЙ shortcuts.xml | диск=ЛЕГИТИМНЫЙ / память=ВРЕД |
| T+4.7с | Атакующий отправляет WM_COMMAND(21000) | |
| T+4.7с | Проверка HMAC: чтение ЛЕГИТИМНОГО файла с диска → ПРОХОДИТ | ПРОВЕРКА ОК |
| T+4.7с | Выполнение: чтение _userCommands[0] из ПАМЯТИ → calc.exe | ЭКСПЛОЙТ |
| T+4.7с | calc.exe запущен (PID 35932) | ПОДТВЕРЖДЕНО |
| Тип | Выполнение произвольных команд |
| Требуется права администратора | Нет |
| Запрос UAC | Нет |
| Обнаруживаемость | Низкая — на диске всё время легитимный файл; нагрузка только в памяти |
| CVSS (оценочно) | AV:L / AC:H / PR:L / UI:N / S:U / C:H / I:H / A:H |
См. poc_8962_toctou.ps1.
Требования:
doLocalConf.xml в папке Notepad++ (портативный режим)config.xml с действительным HMAC для легитимного shortcuts.xml.\poc_8962_toctou.ps1 -NppPath "C:\путь\к\notepad++.exe"
Подтверждено: calc.exe запущен (PID 35932), на диске всё время легитимный shortcuts.xml.
Исправление (коммит 4f7563c) переносит проверку HMAC на этап запуска, одновременно с начальным разбором файла. Проверка и использование теперь работают с одним и тем же объектом в одно и то же время, устраняя окно TOCTOU.
| v8.9.6.2 (уязвимая) | v8.9.6.4 (исправленная) | |
|---|---|---|
| Проверка HMAC | В момент вызова, повторное чтение с диска | При запуске, те же байты, что и при разборе |
| Источник команды | Память, загруженная при запуске | Память, проверенная при запуске |
| Окно TOCTOU | Запуск → Вызов | Устранено |