0xC0000070: Logon Blocked — Account Not Allowed From That Workstation
Published
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.
Did the attacker have the password? Cannot tell from this code alone — correlate with the events around it.
Microsoft's definition
STATUS_INVALID_WORKSTATION
The user account is restricted so that it cannot be used to log on from the source workstation.
Microsoft's 4625 monitoring note: "User logon from unauthorized workstation".
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
What it means
Some accounts are limited to a named set of computers they may log on from — the allowed-workstation list configured on the user account in Active Directory. When a logon request for such an account arrives from a machine that is not on that list, Windows stops the logon and returns 0xC0000070, STATUS_INVALID_WORKSTATION: “The user account is restricted so that it cannot be used to log on from the source workstation.”
Nothing in that wording describes the username or the password. The code tells you the request was rejected because of where it came from, so do not record it in a ticket as a wrong-password event the way you would 0xC000006A, and do not assume the credentials were good either.
Four fields in event 4625 carry the weight here:
- Account Name / Account Domain — the restricted account someone tried to use.
- Workstation Name — the computer name the request claims to come from. It is reported by the client and is sometimes blank, which can itself be the reason the restriction did not match.
- Source Network Address — the client’s IP, usually more trustworthy than the name.
- Logon Type — 3 for network logons such as SMB, 10 for RemoteInteractive, 2 for an interactive console logon.
Domain controllers record the same value in the Error Code of event 4776 when they validate NTLM credentials, so the same code can reach you from two different event IDs.
Is it an attack?
| Pattern | Reading |
|---|---|
| One user, one new or rebuilt PC, failures stop after IT updates the account | Stale allowed-workstation list |
| Service or admin account, failures from a jump host or terminal server | The hop’s computer name was never added to the permitted list |
| Restricted admin account, failures from a workstation that belongs to a different user | Someone is using credentials away from the machine they belong to |
| Blank or unfamiliar Workstation Name with an external Source Network Address | Remote use of the account; treat as suspicious until the source is identified |
| Several restricted accounts failing from one source in a short window | Harvested credentials being tried wherever they will work |
The restriction is the last control that stopped the logon, so the question to answer is whether the person at that source had any business holding those credentials. On accounts that exist precisely to be pinned to a handful of machines, an unlisted source is an incident lead, not a configuration annoyance.
How to investigate
Start by listing which accounts hit the restriction and from where:
SecurityEvent
| where TimeGenerated > ago(7d)
| where EventID == 4625
| where Status =~ "0xc0000070" or SubStatus =~ "0xc0000070"
| summarize Attempts = count(), LastSeen = max(TimeGenerated),
Sources = make_set(IpAddress, 20), Workstations = make_set(WorkstationName, 20),
LogonTypes = make_set(LogonType, 5), Targets = make_set(Computer, 10)
by TargetUserName, TargetDomainName
| order by Attempts desc
Then check the outcome that changes the severity — did the same account and source later succeed somewhere the restriction did not apply?
let blocked = SecurityEvent
| where TimeGenerated > ago(7d) and EventID == 4625
| where Status =~ "0xc0000070" or SubStatus =~ "0xc0000070"
| summarize BlockedAttempts = count(), FirstBlock = min(TimeGenerated)
by TargetUserName, IpAddress;
SecurityEvent
| where TimeGenerated > ago(7d) and EventID == 4624
| join kind=inner blocked on TargetUserName, IpAddress
| where TimeGenerated > FirstBlock
| project TimeGenerated, Computer, TargetUserName, IpAddress, LogonType, WorkstationName, BlockedAttempts
| order by TimeGenerated asc
For each hit, confirm with the account owner or the application team whether that source is theirs. If it is, fix the permitted-computer list rather than removing the restriction. If it is not — or the source is an address nobody claims — treat the credentials as exposed: reset the password, review the account’s other logons across the window, and look for the same source address in failures for other accounts. Without a SIEM, export the Security log as XML from Event Viewer and group the 4625 events by source and status in the free browser 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.
- 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.
- 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.
- 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.
- 0xC0000072 STATUS_ACCOUNT_DISABLED
- 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.
Detect it
Frequently Asked Questions
- Does 0xC0000070 mean the password was correct?
- Microsoft's description says only that "The user account is restricted so that it cannot be used to log on from the source workstation" — it does not state whether the credentials were checked. Treat the code as evidence about where the attempt came from, not as proof that the password was right or wrong, and look for other events from the same source and account before deciding.
- Why does a legitimate user get 0xC0000070 from their own PC?
- The usual cause is the account's allowed-workstation list being out of date — the user was given a new or renamed computer, or they are connecting through a jump host, terminal server or VPN concentrator whose name is not on the list, so the name presented in the logon request does not match any permitted entry. Check the account's permitted computers against the Workstation Name and Source Network Address in event 4625.
- How is 0xC0000070 different from 0xC000006E?
- Both are account restrictions rather than bad credentials, but 0xC000006E is the general restriction result (Microsoft's example is time-of-day restrictions), while 0xC0000070 names the specific reason — the source workstation is not one the account is allowed to use. When 0xC0000070 appears as a Sub Status, read it as the detail behind the broader failure.
- Is 0xC0000070 worth an alert?
- Yes, because it is rare in most environments and Microsoft's own logon monitoring guidance for this code is "User logon from unauthorized workstation". Accounts that carry a workstation restriction are usually administrative or service accounts, so any attempt to use one from an unlisted machine deserves a human look rather than a dashboard tile.
Find 0xC0000070 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.