Researched and written by Rindert Kramer
At Fox-IT, we often do internal penetration tests for our customers. One of the attacks that we perform is password spraying. In a password spraying attack the attacker tries to authenticate as one of the user accounts that is found in Active Directory using a common password. These passwords vary from Summer2017 to Welcome01 and often yield a promising lead to continue towards the goal of becoming domain administrator.
Password history check (N-2)
Most companies for which we perform penetration tests use Active Directory as their primary source for user accounts. These user accounts adhere to the password policy that is configured, whether it’s a domainwide or a finegrained password policy.
Typically, the following settings are configured in such a policy:
- Number of passwords to remember (password history);
- Lockout threshold. After x attempts the domain controller will lock the user account;
- Lockout time. The ‘cool down’ period after a user account has been locked due to too many invalid authentication attempts.
If a user tries to authenticate with a wrong password, the domain controller who handles the authentication request will increment an attribute called badPwdCount. By default, this value is 0. Every time a user fails to authenticate correctly, this value is incremented by the domain controller. Note that this value is not replicated throughout the domain but is only stored on the domain controller the user tries to authenticate to and is synchronized with the domain controller that holds the primary domain controller (PDC) role. Thus the PDC is holding the true value of the badPwdCount-attribute. If the value in the badPwdCount-attribute reaches the threshold that is set in the password policy, the domain controller will lock the account. The user then cannot authenticate until the cool down period is over.
But what happens if you store your password on all sorts of devices (for authenticating with Exchange, Skype For Business, etc.) and you change your password? That would result in Exchange, Windows or any other service trying to authenticate with an invalid password. If everything works correctly, you should be locked out very soon because of this. However, this is not the case.
If NTLM or Kerberos authentication is used and the user tries to authenticate with a password that is the same as one of the last two entries of their password history, the badPwdCount-attribute is not incremented by the domain controller. That means that the domain controller won’t lock the user account after x failed authentication attempts even though the specified password is incorrect.
Password history N-2 is only supported when NTLM or Kerberos authentication is used and if the authentication provider sends the invalid requests to the PDC. This rules out some authentication types such as digest or RADIUS. PEAP and PEAP-CHAP are certificate based and thus the RADIUS server will not send the failed authentication request to the PDC.
MS-CHAPv2 uses your NTLM hash for authentication though, but it is packed together with challenge or response data and a session identifier into a SHA-hash and sent to the authentication provider. A failed authentication is terminated on the authentication provider and is not forwarded to the PDC. The badPwdCount-attribute gets will get incremented after a failed authentication attempt, even if the user used his previous password.
There is a cool script that takes the value of the badPwdCount-attribute into account when doing a password spraying attack. However, there is another attack vector we can abuse.
Let’s say, as an example, that user email@example.com had Spring2017 as his previous password but since he had to change his password, he now uses Summer2017 as password. The attacker queries the primary domain controller for the value of the badPwdCount-attribute for user firstname.lastname@example.org and tries to authenticate with username email@example.com and password Spring2017. The attacker then queries the primary domain controller again for the value of the badPwdCount-attribute again and would conclude that the attribute has not been incremented. The attacker then applies some logic and tries to authenticate with password Summer2017. Since this is the correct password, the attacker will successfully authenticate as firstname.lastname@example.org.
The following code demonstrates how to do this in PowerShell:
The badPwdCount-attribute is, by default, readable for every user account and computer account in the Active Directory. If an attacker has the disposal of credentials of a domain user, he can query the value for the badPwdCount-attribute for any given user. If the attacker does not have credentials of a domain user but does have the credentials of a local administrative account of a domain joined computer, he can use the computer account to authenticate to Active Directory.
To demonstrate this attack, Fox-IT wrote a Metasploit module and a PowerShell script as Proof of Concept (PoC). The script and module will hopefully be available in Metasploit soon but can also be downloaded here: https://github.com/rapid7/metasploit-framework/pull/9195/files
The Metasploit module acts as a wrapper for the PowerShell script and is capable of the following:
- Test credentials for a configurable number of user accounts;
- Show successful authentications;
- Store credentials of users who successfully authenticated in the MetaSploit database;
- Show useraccounts where the badPwdCount-attribute not has been incremented;
- Autoincrement passwords up to two times. That means that Welcome01 becomes Welcome02, etc.
Result of running the module when only checking the password and if the badPwdCount-attribute has been incremented:
Result of brute-forcing (for a maximum of 2 times) when the badPwdCount-attribute has not been incremented:
Please keep the following in mind when using the MetaSploit module:
- Although the script keeps the current badPwdCount-value into account when trying to authenticate, Fox-IT cannot guarantee that the script will not lock out user accounts;
- If a user account is expired and the correct password is used, the user will fail to authenticate but the badPwdCount-attribute will also not increment.
To remediate this issue, Fox-IT advises the following:
- Enforce the use of strong and secure passwords. As you can read everywhere on the internet, a secure password consists of both lower and uppercase characters, numbers and special characters. However, longer passwords take more time to crack it, because the time to crack a password will increase significantly with each added character.
For example, Fox-IT can successfully crack the NTLM hash of a password that has 8 characters within 10 hours, while cracking an NTLM of a password that has 10 characters would take up to eleven years;
- Use passphrases. Passphrases can easily exceed 14 characters, which will also eliminate the possibility of an LM-hash;
- Use your IDS or IPS (or any other system of your choosing) for detecting password spraying attacks.