0xC0000072 Windows logon failure code Triage: medium

0xC0000072: Logon Failed Because the Account Is Disabled

Published · Updated

Windows refused the logon because the account is disabled — the name exists, so the useful question is who or what still tries to use it, from where, and why.

Did the attacker have the password? Cannot tell from this code alone — correlate with the events around it.

Microsoft's definition

STATUS_ACCOUNT_DISABLED

The referenced account is currently disabled and cannot be logged on to.

Microsoft's 4625 monitoring note: "User logon to account disabled by administrator".

Source: [MS-ERREF] NTSTATUS Values · checked against the published table on every build · look up another code

Where it appears

  • Event 4625 (An account failed to log on): the Status or Sub Status field
  • Event 4776 (credential validation, NTLM) on domain controllers: the Error Code field
  • Microsoft Sentinel / Log Analytics: the Status and SubStatus columns of the SecurityEvent table

Every field of that log: Windows Security event log fields

Where it sits in event 4625: an example

Event 4625 · An account failed to log on

Failure Information:

Status:
0xC000006E STATUS_ACCOUNT_RESTRICTION
Sub Status:
0xC0000072 STATUS_ACCOUNT_DISABLED This code

Microsoft's event 4625 documentation: Status is “the reason why logon failed”, Sub Status “additional information about logon failure”. In Microsoft Sentinel they are the Status and SubStatus columns of SecurityEvent.

What it means

0xC0000072 is the NTSTATUS value STATUS_ACCOUNT_DISABLED: “The referenced account is currently disabled and cannot be logged on to.” In Microsoft’s 4625 documentation the code carries the note “User logon to account disabled by administrator.” Windows recognised the account name and refused the logon because the account’s disabled flag is set.

In event 4625 the code usually appears as the Sub Status, under the general account-restriction Status 0xC000006E; on domain controllers it can also appear as the Error Code of an NTLM credential validation (event 4776). The Kerberos form of the same refusal is 0x12 KDC_ERR_CLIENT_REVOKED, and in Entra ID sign-in logs the cloud equivalent is AADSTS50057 (UserDisabled).

Because the account exists, the code is useful in a way “unknown user” failures such as 0xC0000064 are not: it points at a specific identity that someone, or something, still expects to work.

Is it an attack?

PatternReading
Same account, same source host, failures at a regular intervalA service, scheduled task or mapped drive still configured with the account
Logon type 5 (service) or 4 (batch)Almost certainly a stale service or task — find it on the source host
Account of someone who just left, from their old laptop or phoneA forgotten device still signing in
Account of someone who left months ago, from an unfamiliar addressPossible misuse of known credentials — investigate
One source failing against many accounts with 0xC0000072, 0xC000006A and 0xC0000064 mixedPassword spraying or guessing across a username list
Failures shortly before the account is re-enabledSomeone may be waiting for the account to come back

Disabled accounts are attractive to attackers precisely because nobody watches them: a former employee’s or a decommissioned service’s credentials may still be valid elsewhere, and a re-enabled account inherits its old group memberships. A failure stream against a disabled privileged account deserves more urgency than one against an ordinary user.

How to investigate

Group the failures by account, source and logon type:

SecurityEvent
| where TimeGenerated > ago(7d)
| where EventID == 4625 and (Status =~ "0xc0000072" or SubStatus =~ "0xc0000072")
| summarize Failures = count(), Sources = make_set(IpAddress, 10), Workstations = make_set(WorkstationName, 10),
            LogonTypes = make_set(LogonType, 5), Hosts = make_set(Computer, 10),
            FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated)
    by TargetUserName, TargetDomainName
| order by Failures desc

Then look at the sources from the other side — a single source failing across many accounts is guessing, not a stale service:

SecurityEvent
| where TimeGenerated > ago(7d)
| where EventID == 4625
| summarize Accounts = dcount(TargetUserName), Disabled = dcountif(TargetUserName, SubStatus =~ "0xc0000072" or Status =~ "0xc0000072"),
            WrongPassword = dcountif(TargetUserName, SubStatus =~ "0xc000006a"), UnknownUser = dcountif(TargetUserName, SubStatus =~ "0xc0000064")
    by IpAddress, WorkstationName
| where Disabled > 0 and Accounts >= 5
| order by Accounts desc

For a stale service, go to the source host named in Workstation Name or the source address and find the service, task or stored credential still using the account; replace it with a dedicated service account or a group managed service account. For anything you cannot attribute, keep the account disabled, check whether the same credentials succeed against other systems (VPN, cloud, applications that do not use Active Directory), and check when the account was disabled and by whom — event 4725, “A user account was disabled” — and whether a 4722 re-enable followed. The Windows 4625 password-spray rule covers the many-accounts-from-one-source shape. With no SIEM, export the Security log as XML and load it into the free browser log analyzer.

Related codes

  • 0xC000006E STATUS_ACCOUNT_RESTRICTION The username and the authentication information were valid, but a restriction on the account — Microsoft's example is time-of-day restrictions — stopped the logon before it succeeded.
  • 0xC0000234 STATUS_ACCOUNT_LOCKED_OUT The account is locked because the lockout threshold was reached; every further attempt fails with this code until the lockout ends or an administrator unlocks it.
  • 0xC0000193 STATUS_ACCOUNT_EXPIRED
  • 0xC0000071 STATUS_PASSWORD_EXPIRED Windows refused the logon because the account's password has expired and has to be changed — routine at the end of a password cycle for a person, but a broken job when it hits a service account and a lead when it comes from a host the account never uses.
  • 0xC0000064 STATUS_NO_SUCH_USER Someone tried to log on with an account name that does not exist. Occasional typos are normal; bursts of invented names from one source are username guessing or spraying with a generic list.

Detect it

MITRE ATT&CK: T1078T1110

Frequently Asked Questions

Does 0xC0000072 mean the password was correct?
Microsoft's descriptions say only that the account is currently disabled and cannot be logged on to, and the 4625 monitoring note reads "User logon to account disabled by administrator" — neither states whether the password was checked. Treat the code as proof that someone used a real account name, not as proof the password was right, and decide from the source and timing.
Why does 4625 show Status 0xC000006E with Sub Status 0xC0000072?
0xC000006E is the general account-restriction status, and the Sub Status gives the specific restriction — here, that the account is disabled. Search both fields for 0xC0000072, as the queries on this page do, so you catch the code wherever your logs record it.
Who keeps trying to log on with a disabled account?
Most often something configured long ago — a service, scheduled task, mapped drive or mobile device still holding the departed user's or retired service account's credentials, retrying on a timer from the same host. Less often, a former employee, or an attacker working through a list of account names that includes disabled ones, which shows as one source failing against many accounts with mixed status codes.
Should I re-enable an account that shows 0xC0000072?
Only after finding what is using it. Re-enabling restores whatever is behind the failures — including an attacker who has the password. Identify the source host and process first; if it is a legitimate service, give it its own managed account instead of reviving a disabled one, and if nobody owns the source, keep the account disabled and investigate the host.

Find 0xC0000072 in your own logs

Load a Windows Security event export into the free browser analyzer to group failures by account, source IP and status code (nothing is uploaded), or run it through LogTriage for threat-intel enrichment and an AI-written incident report.

Investigating something right now? LogTriage checks every address in the file against threat intelligence and writes the incident report: 10 analyses a month free. The incident pack adds the in-depth AI analysis and files up to 100 MB: 25 analyses for $19, one payment, no subscription. Pricing