Skip to main content
ThreatsSIEM

What is Password Spraying?

Password spraying is an attack that tries one common password, such as Spring2026!, against many accounts before moving to the next, so no single account fails often enough to lock. MITRE ATT&CK lists it as T1110.003. In the logs the pattern is wide and shallow: many usernames, one or two failures each, often sharing a source or user agent.

Definition

Password Spraying
Password spraying is an attack that tries one common password, such as Spring2026!, against many accounts before moving to the next, so no single account fails often enough to lock. MITRE ATT&CK lists it as T1110.003. In the logs the pattern is wide and shallow: many usernames, one or two failures each, often sharing a source or user agent.

How Password Spraying Works

CISA described the method in a 2018 alert on Iranian actors tied to the Mabna Institute: try a single password against many accounts, then a second password, and so on, which it called the "low-and-slow" method. Lockout policies count failures per account, so an attacker who touches each account once or twice per window never trips them. The passwords are the ones people pick when a policy forces a capital, a digit and a symbol: CISA's examples were Winter2018 and Password123!, and ATT&CK notes that the chosen password "may match the complexity policy of the domain".

A spray usually runs in five steps:

  1. Build a username list. Staff pages, social profiles and the email address format do most of the work. ATT&CK records Silent Librarian using collected lists of names and email accounts.
  2. Pick a password that passes the policy, usually a season or company name plus the year and a symbol.
  3. Try it once against every account on a sign-in surface: Microsoft 365 and other SSO portals, Outlook on the web, a VPN gateway, RDP, SMB, or Kerberos sent straight to a domain controller.
  4. Wait out the lockout window, then repeat with the next password.
  5. Use the hits. The valid login often comes later and from a different address than the spray.

Password spraying vs brute force vs credential stuffing

All three sit under T1110 Brute Force in ATT&CK. What tells them apart in your logs is how the attempts are spread across accounts.

Brute force (guessing)Password sprayingCredential stuffing
ShapeMany passwords against one accountOne or a few passwords against many accountsOne leaked username and password pair per account
Where the passwords come fromWordlists or generated combinationsA short list of common passwords that fit the policyBreach dumps from other sites
Failures per accountMany, until lockoutOne or two per windowAbout one
Usernames that do not existFewFew if the list came from your directory, many if it was guessedOften many, because the list belongs to another site
What gives it awayFailure count per accountDistinct accounts per source, user agent or appMany sources, many unknown users, a success from a new address
ATT&CKT1110.001T1110.003T1110.004

Why lockout does not stop it

Every common lockout control counts per account:

  • Active Directory. The default domain policy ships with an account lockout threshold of 0, which means accounts never lock. Windows security baselines recommend 10.
  • Microsoft Entra ID. Smart Lockout locks after 10 failed attempts by default in public cloud tenants, starts with a one-minute lockout that grows on repeat, and keeps separate counters for familiar and unfamiliar locations. It also tracks the last three bad password hashes, so the same wrong password typed again does not add to the count.
  • NIST SP 800-63B-4. Verifiers must cap consecutive failed attempts on a single account at no more than 100.

A spray that sends one guess per account per day stays below all three for as long as it likes. Microsoft measured that on CovertNetwork-1658, a network of hijacked home and small-office routers: in about 80 percent of cases it made only one sign-in attempt per account per day, and Microsoft wrote that "monitoring for multiple failed sign-in attempts from one IP address or to one account will not detect this activity".

The control that sees across accounts and tenants is in the identity provider. Microsoft Entra ID Protection has a password spray risk detection (Entra ID P2), but it only fires once the attacker has validated a user's password. Failed spray attempts against your users generate no detection, so it tells you about a compromise, not an attack in progress.

Where a sprayed password lands in the logs

The protocol that checked the password decides which record you get.

Sign-in surfaceRecordWrong passwordUsername does not existWritten on
SMB or RDP to a Windows host (NTLM)4625SubStatus 0xC000006ASubStatus 0xC0000064The target host
NTLM check of a domain account4776Error code 0xC000006AError code 0xC0000064The domain controller, with a Source Workstation name and no IP address
Kerberos pre-authentication4771Failure Code 0x18 (KDC_ERR_PREAUTH_FAILED)No 4771: 4768 fails with 0x6 (KDC_ERR_C_PRINCIPAL_UNKNOWN)Domain controllers only, Client Address in ::ffff: form
Microsoft Entra ID (Microsoft 365, Azure)SigninLogsResultType 50126ResultType 50034Entra ID, exported to Sentinel or Log Analytics
AD FS (federated domains)AD FS audit events 411 and 342User name or password incorrectSame eventsAD FS servers; 516 marks an extranet lockout

ATT&CK notes that attackers lean on LDAP and Kerberos because they are less likely to raise the 4625 that failed SMB logons produce, and Kerbrute, a common tool for this, says the same in its README: pre-authentication failures do not raise 4625, and its passwordspray mode produces 4768 and 4771 on the domain controller instead. A rule built only on 4625 misses a Kerberos spray entirely. Federation moves the evidence too: for a federated domain, Microsoft's password spray playbook notes that successful sign-ins are stored in Entra ID while the failures stay with the identity provider, so on AD FS the spray is in the AD FS logs, not in SigninLogs.

The SubStatus split also tells you where the attacker's list came from. 0xC000006A means the account exists and the password was wrong; a spray run from a list built off your own directory is mostly that. A wall of 0xC0000064 means the attacker is guessing usernames too, and Microsoft's 4625 guidance calls several of those in a row a possible sign of user enumeration. The Windows event IDs cheat sheet covers the rest of the authentication events, and NTLM vs Kerberos explains why one guess can leave two different records.

Which results mean the password was right

Microsoft's playbook separates two outcomes. In a password compromise, the attacker guessed the password but another control, such as MFA, kept them out. In an account compromise, they got in. Both mean the password is known. The playbook tells you to pull the successful and the interrupted sign-ins for the attack window, because those are your accounts of interest. In SigninLogs, a sprayed account that shows anything other than 50126 from the spraying source deserves a look: 0 is a sign-in, 50074 means strong authentication was required and the user did not pass the MFA challenge, and 53003 means Conditional Access blocked the sign-in, which Microsoft only evaluates after first-factor authentication has completed. 50053 is ambiguous: Microsoft uses it both for an account locked by repeated bad attempts and for a sign-in blocked because the IP address has a record of malicious activity.

Two campaigns built to beat per-account thresholds

Midnight Blizzard against Microsoft, 2024. Microsoft detected the intrusion on 12 January 2024. The actor, Russia's Midnight Blizzard (also tracked as NOBELIUM), compromised a legacy, non-production test tenant account that did not have MFA enabled. Microsoft says the spray was tailored to a limited number of accounts with a low number of attempts, launched from distributed residential proxy infrastructure, which made IP-based indicators useless. From that account the actor found a legacy test OAuth application with elevated access to the corporate environment and used it to give OAuth applications it controlled access to Exchange Online and to corporate mailboxes.

CovertNetwork-1658, 2023 to 2024. Microsoft tracks this as a network of compromised small-office and home routers, most of them made by TP-Link, also known as Quad7. It averaged about 8,000 active devices, around 20 percent of them spraying at any time, and the average node stayed up for roughly 90 days. The Chinese actor Storm-0940 used credentials from these sprays, in some cases on the same day they were obtained.

A simulated case

Simulated example generated by SOCSimulator Research. Users, hosts and addresses are invented; event IDs, fields and codes are Microsoft's.

TimeGenerated  Event  Computer  Account       Client Address       Code
09:02:11       4771   DC01      a.keane       ::ffff:10.20.30.45   0x18
09:02:11       4771   DC01      b.moreno      ::ffff:10.20.30.45   0x18
09:02:12       4768   DC01      c.lindqvist   ::ffff:10.20.30.45   0x6
09:02:12       4771   DC01      d.osei        ::ffff:10.20.30.45   0x18
               ... 409 more 4771 rows from 10.20.30.45 by 09:06, one per account
09:04:57       4768   DC01      svc_backup    ::ffff:10.20.30.45   0x0
09:31:40       4624   FS02      svc_backup    10.20.30.45          Logon Type 3

One internal address checks a password against more than 400 accounts in four minutes, once each, over Kerberos only. No account locks and no 4625 appears anywhere, so a failed-logon rule stays quiet. The source is a workstation in the user VLAN, which makes it a second incident: something is running a spray tool on that machine. The case turns on the 4768 with result 0x0: svc_backup accepted the password, and 27 minutes later the same address logs on to FS02 with it over the network (logon type 3; see Windows logon types). Reset the service account with its owner, isolate 10.20.30.45 and look for the tool, and search for every other 0x0 from that address in the window. The alert triage guide covers how to write up a case like this one.

Detecting password spraying with KQL

The first query scores on-premises sources by how many accounts they failed against, across 4625 and 4771.

// Windows: accounts failed per source address, 4625 and 4771
let window = 1h;
SecurityEvent
| where TimeGenerated > ago(window)
| where (EventID == 4625 and SubStatus in~ ("0xc000006a", "0xc0000064"))
    or (EventID == 4771 and Status =~ "0x18")
| extend Source = replace_string(IpAddress, "::ffff:", "")
| summarize Attempts = count(), Accounts = dcount(TargetUserName),
    UnknownUsers = countif(SubStatus =~ "0xc0000064"),
    Events = make_set(EventID), Targets = make_set(Computer, 10) by Source
| extend PerAccount = round(1.0 * Attempts / Accounts, 1)
| where Accounts >= 20 and PerAccount <= 2
| order by Accounts desc

The second does the same for Entra ID and then lists what the sprayed accounts did next from the same addresses.

// Entra ID: spraying sources, then non-50126 results from those sources
let window = 1d;
let sprayers = SigninLogs
| where TimeGenerated > ago(window) and ResultType == "50126"
| summarize Failures = count(), Accounts = dcount(UserPrincipalName),
    FirstFail = min(TimeGenerated) by IPAddress
| where Accounts >= 10 and 1.0 * Failures / Accounts <= 2;
SigninLogs
| where TimeGenerated > ago(window)
| where ResultType !in ("50126", "50034", "50053")
| join kind=inner sprayers on IPAddress
| where TimeGenerated > FirstFail
| project TimeGenerated, UserPrincipalName, IPAddress, ResultType, ResultDescription,
    AuthenticationRequirement, ClientAppUsed, AppDisplayName, Accounts

Neither catches a spray like CovertNetwork-1658's, where every address sends a handful of attempts. Microsoft's playbook lists the low-and-slow indicators for that case: failures that walk the global address list in order, attempts that repeat the same attributes (user agent, target app, IP block or location), and timing more regular than people produce. The third query groups a week of single daily failures by what they share.

// Low and slow: accounts with exactly one 50126 a day, grouped by user agent and app
SigninLogs
| where TimeGenerated > ago(7d) and ResultType == "50126"
| summarize DailyFails = count(), IP = take_any(IPAddress)
    by UserPrincipalName, Day = bin(TimeGenerated, 1d), UserAgent, AppDisplayName
| where DailyFails == 1
| summarize Accounts = dcount(UserPrincipalName), Days = dcount(Day), SourceIPs = dcount(IP)
    by UserAgent, AppDisplayName
| where Accounts >= 25
| order by Accounts desc

In a large tenant a mainstream browser string will top that list on typos alone, so run it over a normal week first. The rows worth reading are unusual or truncated user agents, apps people do not sign in to by hand, and a SourceIPs count close to Accounts. The queries follow Microsoft's documented SecurityEvent and SigninLogs schemas and have not been run against a live workspace by SOCSimulator; set the thresholds from your own baseline. Kusto Query Language covers the operators, and alert correlation and threat hunting cover where these fit in a detection program.

Preventing password spraying

  • MFA on every account, starting with the ones nobody watches. Midnight Blizzard got in through a test tenant account without MFA. With MFA, a guessed password becomes a password compromise instead of an account compromise. See MFA.
  • Block legacy authentication. Microsoft's CovertNetwork-1658 guidance says legacy protocols cannot enforce MFA, so blocking them stops sprayers from using that gap. ClientAppUsed values such as IMAP, POP and SMTP in SigninLogs show who still uses them.
  • Ban the passwords sprayers try. NIST SP 800-63B-4 requires checking new passwords against a blocklist of commonly used, expected or compromised values. Season plus year plus symbol belongs on it.
  • Set lockout so it slows guessing without handing out a denial of service. In hybrid setups Microsoft recommends an AD DS threshold two to three times the Entra ID one, so Smart Lockout acts before on-premises accounts lock. ATT&CK warns that too strict a policy lets an attacker lock every account on purpose.
  • Reset the passwords of every account the spray touched. That is Microsoft's advice after a spray, and it covers the case your queries miss: a correct guess used later, from an address you never tied to the attack.
  • Do not plan on IP blocklists. Residential proxies and hijacked home routers are the infrastructure in both campaigns above.

Password Spraying in SOC Operations

A spray alert rarely arrives with a clear severity. Most of what it counts is failures, and failures are cheap. Triage it with three questions, in this order. Did any account the source touched get a result other than a bad password? Is the source inside your network? Does the username list look like your directory or like a guess? A success, an MFA interruption or a Conditional Access block on a sprayed account moves the case from attempted to password known, and that account gets a reset and a session revocation whether or not the attacker got in. An internal source turns one alert into two, because something on that host is running the tool. A list full of 0xC0000064 or 50034 names you never had points to a broad, untargeted run; a clean list of real users means someone has already mapped your staff. Record which log the evidence came from. A Kerberos spray against a domain controller and an Entra ID spray against Microsoft 365 have different owners, and they are fixed in different places. When the counts look normal but the same user agent keeps failing once a day across your users, treat it as a slow spray and hunt for it.

Free

Practice Password Spraying in a Real SOC

SOCSimulator provides hands-on training with realistic SIEM, XDR, and Firewall interfaces. Build real analyst skills investigating password spraying scenarios with zero consequences, free.

Frequently Asked Questions

What is the difference between password spraying and brute force?
A classic brute force attack throws many passwords at one account and trips its lockout counter. Password spraying turns that around: one or a few common passwords against many accounts, one try each per window, so no counter fills up. In the logs, brute force piles failures on a few accounts; a spray spreads one or two failures across dozens or hundreds of usernames.
Is password spraying the same as credential stuffing?
No. Spraying guesses: it tries a common password such as Spring2026! against accounts it has listed. Credential stuffing replays username and password pairs leaked from another site, betting on reuse. Both show up as about one failure per account, but stuffing usually comes from many more source addresses and hits many usernames that do not exist in your directory. ATT&CK files them as T1110.003 and T1110.004.
Which logs and event IDs show password spraying?
Look in the log of whatever checked the password. SMB and RDP spraying against Windows hosts writes 4625 with SubStatus 0xC000006A (bad password) or 0xC0000064 (no such user). A Kerberos spray writes 4771 with failure code 0x18 on the domain controller, and NTLM checks of domain accounts write 4776 there. In Entra ID, look for ResultType 50126 in SigninLogs; for a federated domain the failures sit in the AD FS logs instead. No single event proves a spray; the count of distinct accounts per source does.
How do you detect a password spraying attack?
Count distinct accounts per source, not failures per account. A source with bad-password results against 20 or more accounts and two or fewer tries each is the classic shape. Then check whether any of those accounts had a different result from the same source: a success, an MFA interruption (50074) or a Conditional Access block (53003) means the password is known. For slow sprays, group single daily failures by user agent and app.
How do you prevent password spray attacks?
Require MFA on every account, including test and service accounts, and block legacy protocols such as IMAP and POP that cannot ask for it. Ban the passwords sprayers try, as NIST SP 800-63B-4 requires. Keep lockout as a speed bump, not the main control, and after a spray reset the password of every account it touched. Do not rely on blocking IPs: recent campaigns ran through residential proxies and hijacked routers.

Sources

More Threats Terms

Career Path

Threat Hunter Career Guide: Salary & Skills

Threat Hunters do not wait for alerts. You develop hypotheses based on threat intelligence and adversary behavior models…

Read more
Career Path

Incident Responder Career Guide: Salary & Skills

Incident Responders lead the technical response when confirmed breaches happen. You coordinate containment, run forensic…

Read more
Career Path

SOC Analyst (Tier 2) Career Guide: Salary & Skills

Tier 2 SOC Analysts handle the investigations that Tier 1 escalates. You dig into multi-stage attacks, coordinate contai…

Read more
Comparison

SOCSimulator vs Hack The Box: Comparison

Different tools for different career paths. SOCSimulator trains defensive analysts. Hack The Box trains offensive securi…

Read more
Tool

SIEM Training Console: SOCSimulator

The SIEM console in SOCSimulator replicates the workflow of enterprise platforms like Splunk Enterprise Security, Micros…

Read more
Technique

MITRE ATT&CK® Techniques: Detection Training Library

Browse all MITRE ATT&CK® techniques with detection strategies and example alerts.

Read more
Career Path

Cybersecurity Career Paths: 2026 Guide

Explore SOC analyst career paths with salary data, required skills, and certification roadmaps.

Read more
Playbook

SOC Investigation Playbooks: Step-by-Step Guides

Practitioner investigation playbooks with decision trees and real SIEM queries.

Read more
Feature

Shift Mode: Real-Time SOC Simulation

Practice alert triage under realistic time pressure with SLA timers and noise injection.

Read more
Feature

Operations: Guided Training Operations

Structured CTF-style investigation operations covering real-world attack scenarios.

Read more
Blog

SOCSimulator Blog: Security Training Insights

Articles on SOC analyst skills, detection engineering, and career development.

Read more
Feature

SOCSimulator Pricing: Free Plan Available

Compare free and Pro tiers.

Read more