CVE-2026-50343(CWE-269: Improper Privilege Management): повышение привилегий через Windows InstallService
Введение
Уязвимость связана с тем, что стандартный пользователь может изменять определённые ветки HKLM регистра, которые впоследствии читаются и обрабатываются InstallService в привилегированном контексте. В результате системный сервис может загрузить контролируемую пользователем DLL и выполнить её с привилегиями NT AUTHORITY\SYSTEM.
InstallService и plugin state
InstallService является частью Windows, связанной с установкой и обновлением приложений. Сервис работает с привилегиями NT AUTHORITY\SYSTEM, поэтому код, загруженный в его процесс, также выполняется в контексте SYSTEM.
Для обработки plugin InstallService использует состояние в реестре:
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\InstallService\State
В рассматриваемой цепочке важны:
PlugInList StaticPluginMap
Упрощённо их роль выглядит так:
PlugInList
│
└── название плагина и его состояние
StaticPluginMap
│
└── название плагина → что подгрузитьПри обработке plugin InstallService проходит через внутреннюю цепочку выбора и активации:
InstallServiceControl::CreateInstallServiceWork
↓
InstallQueue2::CreateWork
↓
CreateInstallServiceWorkByPlugin
↓
PluginHelpers::IsPluginAvailable
↓
PluginHelpers::GetPluginFromStaticMap
↓
PluginHelpers::ActivatePluginНа уязвимых сборках стандартный пользователь, состоящий в группе NT AUTHORITY\INTERACTIVE может создавать необходимые ключи и записывать значения в эти разделы. После этого те же данные используются привилегированным InstallService.
Интересная особенность CVE заключается в том, что StaticPluginMap может участвовать в двух вариантах цепочки загрузки DLL:
StaticPluginMap → путь к DLL → загрузка DLL
StaticPluginMap → CLSID
↓
CoCreateInstance()
↓
InprocServer32
↓
DLLОба варианта приводят к загрузке контролируемого кода в контексте InstallService.
StaticPluginMap -> путь к DLL
В StaticPluginMap непосредственно указывается путь к контролируемой DLL:
StaticPluginMap └── <plugin_name> = C:\...\payload.dll
Одновременно создаётся plugin entry:
PlugInList └── <plugin_name> = 1
Подготовленное состояние выглядит следующим образом:
HKLM
└── SOFTWARE
└── Microsoft
└── Windows
└── CurrentVersion
└── InstallService
└── State
├── PlugInList
│ └── <plugin_name> = 1
│
└── StaticPluginMap
└── <plugin_name> = C:\...\payload.dllРеализация уязвимости
Данная статья представлена исключительно в образовательных целях. Red Team сообщество "GISCYBERTEAM" не несёт ответственности за любые последствия ее использования третьими лицами.
Подготовленного registry state недостаточно - необходимо инициировать работу InstallService.
Сделать это предлагается вызовом:
Windows.ApplicationModel.Store.Preview.InstallControl.AppInstallManager.SearchForAllUpdatesAsync()
Как защищаться
Основная мера защиты — установка исправления Microsoft.
Уязвимость была исправлена 14 июля 2026 года. Для затронутых версий Windows необходимо установить соответствующее накопительное обновление безопасности и убедиться, что система находится на исправленном build.
До установки исправления для обнаружения можно контролировать изменения:
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\InstallService\State
PlugInList StaticPluginMap
Подозрительными признаками являются:
- создание новых
plugin entries; - изменение
StaticPluginMap; - значения, указывающие на пользовательские каталоги;
- изменение этих ключей из пользовательского контекста;
- загрузка нестандартных
DLLсистемными процессами.
Для COM-варианта полезно дополнительно сопоставлять:
StaticPluginMap
↓
CLSID
↓
HKLM\SOFTWARE\Classes\CLSID\<CLSID>\InprocServer32
↓
DLLОтдельно стоит отслеживать загрузку DLL из пользовательских и writable-каталогов системными процессами.
После установки обновления имеет смысл проверить права на:
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\InstallService\State
и убедиться, что стандартный пользователь не может изменять plugin state.
Заключение
CVE-2026-50343 возникает из-за нарушения границы доверия между стандартным пользователем и привилегированным InstallService.
Низкопривилегированный пользователь получает возможность управлять plugin state:
PlugInList StaticPluginMap
после чего InstallService использует эти данные для активации plugin.
Существует два основных варианта цепочки:
StaticPluginMap
│
┌─────────┴─────────┐
│ │
▼ ▼
DLL path CLSID
│ │
│ CoCreateInstance()
│ │
│ InprocServer32
│ │
└─────────┬─────────┘
▼
DLL load
│
▼
InstallService
SYSTEM
│
▼
Code executionВ первом варианте StaticPluginMap непосредственно содержит путь к DLL.
Во втором он содержит CLSID. InstallService передаёт его в CoCreateInstance(), после чего COM получает DLL через InprocServer32.
Таким образом, CLSID — не обязательная часть эксплуатации. Это один из механизмов, через который контролируемый StaticPluginMap может быть доведён до загрузки DLL.