0xC000006E Windows logon failure code Triage: medium

0xC000006E: Windows Logon Blocked by an Account Restriction

Published

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.

Did the attacker have the password? Yes — the password was accepted; the sign-in failed at a later step. Treat the credential as known to whoever attempted it.

Microsoft's definition

STATUS_ACCOUNT_RESTRICTION

Indicates a referenced user name and authentication information are valid, but some user account restriction has prevented successful authentication (such as time-of-day restrictions).

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
  • Microsoft Sentinel / Log Analytics: the Status and SubStatus columns of the SecurityEvent table

What it means

0xC000006E is STATUS_ACCOUNT_RESTRICTION. Windows resolved the account name and accepted the authentication information, then refused the logon because of a restriction on the account itself. Microsoft’s example is time-of-day restrictions; the same status covers the family of “the credentials are fine, the account may not log on like this right now” conditions.

For triage the useful half of that sentence is the first half: the submitted credentials were valid. This is not a guessing failure like 0xC000006A (real account, wrong password) or 0xC0000064 (name does not exist). Someone, or something, had working credentials.

In event 4625 the code can appear in Status — in which case Sub Status carries the specific reason — or as the Sub Status itself. Read it together with Logon Type (3 network, 10 RemoteInteractive, 5 service, 4 batch) and Source Network Address, which tell you what kind of access was attempted and from where.

Is it an attack?

PatternReading
One user, logon type 2 or 10, outside their working hoursLogon-hours or workstation restriction doing its job
Service or batch logon failing on a fixed schedule from one internal hostA scheduled task or service using an account whose restrictions exclude that host or time
A single account, repeatedly, right after an administrator disabled or expired itSomething still holds the old credentials — a stored password, a token, or a person
One external or unfamiliar address, one account, valid credentials each timeCredential theft or reuse blocked only by account state — escalate
One source, 0xC000006E across several accountsSomeone is working through a set of credentials they already have (T1078)

The distinction that matters: an account disabled during offboarding failing from the ex-employee’s laptop is cleanup; the same code from a host that should never touch that account is an incident.

How to investigate

Start by listing which accounts are hitting the restriction, from where, and with which specific Sub Status:

SecurityEvent
| where TimeGenerated > ago(7d)
| where EventID == 4625 and (Status =~ "0xc000006e" or SubStatus =~ "0xc000006e")
| summarize Attempts = count(), Sources = dcount(IpAddress),
            SubStatuses = make_set(SubStatus, 10), LogonTypes = make_set(LogonType, 5),
            SourceList = make_set(IpAddress, 20), Hosts = make_set(Computer, 10)
    by TargetUserName, TargetDomainName
| order by Attempts desc

Then answer the question that sets the severity — did the same account and source ever succeed once the restriction no longer applied?

let restricted = SecurityEvent
    | where TimeGenerated > ago(7d) and EventID == 4625
    | where Status =~ "0xc000006e" or SubStatus =~ "0xc000006e"
    | summarize Fails = count(), LastFail = max(TimeGenerated) by TargetUserName, IpAddress;
SecurityEvent
| where TimeGenerated > ago(7d) and EventID == 4624
| join kind=inner restricted on TargetUserName, IpAddress
| where TimeGenerated > LastFail
| project TimeGenerated, Computer, TargetUserName, IpAddress, LogonType, WorkstationName, Fails
| order by TimeGenerated desc

If the source is unrecognised, treat the password as compromised: reset it, check which sessions and tokens exist for the account, and review what the account could reach had the restriction not been there. If the source is a known server, confirm the account’s logon hours, its logon workstations list and any authentication policy before changing anything — the fix is usually configuration, not a reset. Without a SIEM, export the Security log as XML from Event Viewer and group the 4625 events by source and Sub Status in the free browser analyzer.

Related codes

  • 0xC000006F STATUS_INVALID_LOGON_HOURS
  • 0xC0000070 STATUS_INVALID_WORKSTATION The account is restricted to a list of computers it may log on from, and this attempt came from one that is not on the list, so Windows rejected it because of where it came from rather than because of the name or the password.
  • 0xC0000072 STATUS_ACCOUNT_DISABLED
  • 0xC0000071 STATUS_PASSWORD_EXPIRED
  • 0xC000006A STATUS_WRONG_PASSWORD The account exists and the password was wrong. One event is a typo; many against one account is brute force; one source failing across many real accounts is password spraying.
  • 0xC000006D STATUS_LOGON_FAILURE The logon was rejected as invalid without saying which half was wrong — it is the general failure result that event 4625 usually carries in Status, with the real reason in Sub Status.

Detect it

MITRE ATT&CK: T1078T1078.002

Frequently Asked Questions

Does 0xC000006E mean the password was correct?
Yes. Microsoft's NTSTATUS description says the referenced user name and authentication information are valid and that a user account restriction prevented the authentication. Treat the credentials as known to whoever sent the attempt, and judge the event by whether that person should have them.
What restriction actually blocked the logon?
0xC000006E does not say on its own. When it appears in the Status field of event 4625, read Sub Status, because Windows has separate codes for a disabled account (0xC0000072), an expired account (0xC0000193), an expired password (0xC0000071), a logon-hours violation (0xC000006F) and a workstation restriction (0xC0000070). If Sub Status is also 0xC000006E, check the account's logon hours, logon workstations and any authentication policy silo it belongs to.
Why do I see 0xC000006E for service accounts at the same time every night?
That pattern usually means the account has logon-hours restrictions or a workstations list that does not include the host running the job, and the schedule falls outside them. Confirm with the account's properties in Active Directory and with the Logon Type and Source Network Address in the event before assuming an intrusion.
Is a burst of 0xC000006E from one source worth escalating?
Yes, more than the same volume of wrong-password failures. Each event says the credentials offered were valid, so repeated hits from one address mean someone holds working credentials for one or more accounts and is being stopped only by account state or policy. Verify the source is a known host and check for any 4624 success from it afterwards.

Find 0xC000006E 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.