Event ID 4648: Explicit Credentials Used — RunAs, Tasks, Lateral Moves
Published
A process supplied another account's credentials on purpose — routine for scheduled tasks and RunAs, but it is also the trace an attacker leaves when switching identity before reaching another machine.
Logged on: The computer where the process that supplied the credentials ran — Microsoft describes the event as generated "when a process attempts an account logon by explicitly specifying that account's credentials", and Target Server Name holds "localhost" when that process was run locally.
Microsoft's title
4648(S): A logon was attempted using explicit credentials.
Source: Microsoft's event 4648 documentation · field names checked against it on every build
Fields that matter in an investigation
| Field | XML / Sentinel | What it tells you |
|---|---|---|
| Security ID | SubjectUserSid | SID of the account that requested the new logon session with explicit credentials — the identity already holding a session on this computer, and the one Microsoft's monitoring guidance tells you to watch for high-value accounts. |
| Account Name | SubjectUserName | Name of the account that requested the new logon session with explicit credentials; compare it with the account whose credentials were used to spot an identity switch. |
| Logon ID | SubjectLogonId | Hexadecimal value that correlates this event with recent events carrying the same Logon ID, for example 4624 — it ties the RunAs back to the session that performed it. |
| Account Name | TargetUserName | The name of the account whose credentials were used — the identity the process authenticated as. |
| Account Domain | TargetDomainName | Domain or computer name for the account whose credentials were used; for local accounts it holds the computer name, and well-known principals such as LOCAL SERVICE show "NT AUTHORITY". |
| Logon GUID | TargetLogonGuid | GUID that can correlate this event with 4769 on a domain controller and with 4624 on the same computer; it appears as all zeros when the parameter was not captured. |
| Target Server Name | TargetServerName | The name of the server on which the new process was run; the value is "localhost" if the process was run locally, so anything else names the remote destination of the credential use. |
| Additional Information | TargetInfo | Extra target detail accompanying the request — Microsoft states there is no detailed information about this field in the event documentation, so treat it as context only. |
| Process ID | ProcessId | Hexadecimal process ID of the process which was run using explicit credentials; convert it to decimal to match Task Manager, or correlate it with the New Process ID in 4688. |
| Process Name | ProcessName | Full path and name of the executable for the process — Microsoft's guidance is to flag paths outside standard folders such as System32 or Program Files, and restricted substrings in the name. |
What it records
Event 4648 belongs to the Audit Logon subcategory. Microsoft’s description is short and worth taking literally: “This event is generated when a process attempts an account logon by explicitly specifying that account’s credentials.” The documentation adds where that normally happens — “This most commonly occurs in batch-type configurations such as scheduled tasks, or when using the ‘RUNAS’ command” — and warns that “It is also a routine event which periodically occurs during normal operating system activity.”
The event is built from four blocks. Subject names who asked: Security ID, Account Name, Account Domain and a Logon ID that points back at the session already running on the box. Account Whose Credentials Were Used names the borrowed identity: Account Name, Account Domain and a Logon GUID that can tie the request to a 4769 service-ticket request on a domain controller. Target Server holds Target Server Name — the name of the server on which the new process was run, with “localhost” when it ran locally — plus Additional Information, a field Microsoft explicitly leaves undocumented. Process Information gives the hexadecimal Process ID and the full path of the executable, and Network Information gives Network Address and Port.
The event requires no particular server role and is available from Windows Vista and Windows Server 2008 onward.
When it matters
The useful signal is the pairing of subject, borrowed account and process path.
| Pattern | Reading |
|---|---|
| Subject and used account identical, process in System32, Target Server Name “localhost” | The routine operating-system activity Microsoft warns about |
| A standard user account supplying a domain-admin account’s credentials | Privilege switch on a host that should not hold those credentials |
| Credentials for one high-value account used from many workstations | Microsoft’s high-value-account monitoring case, tracked on “Account Whose Credentials Were Used\Security ID” |
| Process Name outside System32 or Program Files, or in a temporary folder | Microsoft’s guidance is to monitor process names not in a standard folder, or in a restricted folder |
| Process name containing restricted substrings — the documented examples are “mimikatz” or “cain.exe” | Credential tooling, not administration |
| Credentials for a service or disabled account used outside working hours | Microsoft’s anomaly and non-active-account recommendations |
| Network Address outside your internal ranges for an account that should only be used internally | Microsoft’s check that Network Address is from the internal IP address list |
Two more of Microsoft’s recommendations are easy to operationalise: if the subject should not know or use the credentials of the account whose credentials were used, the event is worth an alert on its own; and account names that break your naming conventions in either field deserve review.
How to investigate
Start with identity switches, ignoring machine accounts and the self-referential noise:
SecurityEvent
| where TimeGenerated > ago(24h)
| where EventID == 4648
| where SubjectUserName !endswith "$" and TargetUserName !endswith "$"
| where tolower(SubjectUserName) != tolower(TargetUserName)
| summarize Attempts = count(), UsedAccounts = dcount(TargetUserName),
AccountList = make_set(TargetUserName, 20), Processes = make_set(ProcessName, 10)
by Computer, SubjectUserName, SubjectDomainName
| order by UsedAccounts desc, Attempts desc
One subject cycling through several distinct accounts on one host is the shape worth chasing; a long tail of one-to-one pairs is usually administration.
Next, apply the process-path guidance directly:
SecurityEvent
| where TimeGenerated > ago(7d)
| where EventID == 4648
| where ProcessName !startswith "C:\\Windows\\System32\\"
| where ProcessName !startswith "C:\\Program Files"
| project TimeGenerated, Computer, SubjectUserName, SubjectDomainName,
TargetUserName, TargetDomainName, ProcessName, IpAddress
| order by TimeGenerated desc
Then use the Subject Logon ID, which Microsoft documents as correlating with recent events carrying the same value such as 4624, to find out who was sitting in the session that borrowed the credentials:
let explicit = SecurityEvent
| where TimeGenerated > ago(24h) and EventID == 4648
| project ExplicitTime = TimeGenerated, Computer, SubjectLogonId,
RunAsBy = SubjectUserName, CredentialsUsed = TargetUserName,
ExplicitProcess = ProcessName;
SecurityEvent
| where TimeGenerated > ago(24h) and EventID == 4624
| join kind=inner explicit on Computer, $left.TargetLogonId == $right.SubjectLogonId
| project ExplicitTime, SessionStart = TimeGenerated, Computer, RunAsBy, CredentialsUsed,
ExplicitProcess, LogonType, SourceIp = IpAddress
| order by ExplicitTime desc
If the originating 4624 is a type 10 session from an unfamiliar address, the explicit-credential use belongs to whoever opened that session, not to the named administrator.
From there, pivot outward. The Process ID converts to the decimal value you can match against New Process ID in 4688, giving you the command line that ran. 4672 on the same Logon ID tells you the session already held privileges. On the destination, look for the matching 4624 and, if the attempt failed, the 4625 and its Sub Status — 0xC000006A for a wrong password against a real account, 0xC0000064 for a name that does not exist. On a domain controller, the Logon GUID can link the request to a 4769 service-ticket request, which shows which service the borrowed identity went after; Kerberos pre-authentication failures carry codes such as 0x18. Repeated failed credential use from one source is spraying behaviour, which the Windows 4625 password-spray rule groups for you. Without a SIEM, export the Security log as XML from Event Viewer and open it in the free browser log analyzer.
Related events and codes
- Event ID 4624 An account was successfully logged on.
- Event ID 4625 An account failed to log on.
- Event ID 4672 Special privileges assigned to new logon.
- Event ID 4688 A new process has been created.
- Event ID 4698 A scheduled task was created.
- Event ID 4769 A Kerberos service ticket was requested.
- Event ID 4776 The computer attempted to validate the credentials for an account.
- 0xC000006A 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 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.
- 0x18 The domain controller rejected the pre-authentication data sent with a ticket request — Microsoft's listed cause is that the wrong password was provided; repeated 0x18 events for one account are a brute-force indicator.
Detect it
Frequently Asked Questions
- Does 4648 mean the credentials were accepted?
- Not on its own. Microsoft describes the event as generated when a process attempts an account logon by explicitly specifying that account's credentials, so it records the attempt made on this computer. The outcome shows up where the authentication landed — 4624 for a successful session, 4625 for a failure, and on a domain controller 4769 or 4776.
- Why do I see constant 4648 events where the subject and the target account are the same?
- Microsoft states that this is "also a routine event which periodically occurs during normal operating system activity", and the documented example is svchost.exe with Target Server Name "localhost" and Network Address ::1. Baseline those per host and investigate the ones where the account whose credentials were used differs from the subject.
- How is 4648 different from 4624?
- 4648 is written where the credentials were supplied — the machine running RunAs, the scheduled task or the tool. 4624 is written on the computer that was accessed, where the session was created. Seeing 4648 on a workstation and 4624 on a server a second later gives you both ends of the same credential use.
- What should I read in Network Address on a 4648?
- Microsoft defines it as the IP address of the machine from which the logon attempt was performed, with ::1 or 127.0.0.1 meaning localhost, and Port as the source port, which is 0 for interactive logons. The destination of the credential use is Target Server Name, not Network Address.
Find every 4648 in your own logs
Load a Windows Security event export into the free browser analyzer to group events by account, source address and status, with password spraying, brute force and lockout storms flagged. Nothing is uploaded.