How I Cracked a 128-bit Password

Sally Vandeven//

TL;DR – Passwords stored using reversible encryption, even if they are VERY LONG,  can be trivially reversed by an attacker.

Password cracking is quite enjoyable. It is very satisfying to launch Hashcat, throw a bunch of hashes at it and watch the progress over minutes, which turns into hours and then days. It does this all while you are working on another test, walking the dog, or perhaps sipping cocktails on the beach.

A password cracker works by taking a potential password, say Autumn2018, and calculating its hash. Hashcat then compares the newly calculated hash that represents Autumn2018 to the list of hashes you have given it. If it finds one or more matches it means those accounts are using the password Autumn2018.

Got one…

Got another…

…and so on.

It all starts with extracting the hashes from a domain controller. Most often we elevate to domain admin and logon to a domain controller to get the files needed.

Psssst! Sometimes it is even easier. Sometimes, there is a backup file, accessible by a lower-privileged account, that contains the Active Directory (AD) database.

Since you cannot copy the active, running AD database (it is locked while in use) we create a VSS snapshot and copy the ntds.dit file along with the SYSTEM registry hive that contains the BOOTKEY needed to extract hashes. We typically do this with the built-in ntdsutil command like so:

Then we can use the Impacket secretsdump Python script to actually pull the hashes from database. -system SYSTEM -ntds ntds.dit LOCAL -outputfile breakme

I am used to seeing the the *.NTDS file that contains the NTLM hashes but imagine my surprise when on a recent test the script also output a file with the extension “.CLEARTEXT”. (To protect the innocent, this was re-created in the lab, but this did happen on an actual test.)

The secretsdump script writes all hashes out to files using the prefix “breakme” as specified by the outputfile parameter. In this case, it found NTLM hashes, cleartext hashes and Kerberos keys. As it turns out, the “CLEARTEXT” file contained cleartext passwords for the associated users, including several passwords that were literally 128 characters in length!

For this blog post we, of course, are zooming in on the CLEARTEXT file:

I had never seen this before. This is the thing of legends. There was literally an output file that contained each user account and a corresponding cleartext password. No cracking required. Of course I immediately spot-checked some of these accounts (cough, cough a domain admin account) to see if the passwords were valid and they were!!  After some investigation, I learned that there are at least a couple different mechanisms that force the storage of cleartext credentials.

Note: Cleartext does not really mean that the passwords are stored as is. They are stored in an encrypted form using RC4 encryption. The key used to both encrypt and decrypt is the SYSKEY, which is stored in the registry and can be extracted by a domain admin.This means the hashes can be trivially reversed to the cleartext values, hence the term “reversible encryption”.

For an account that stores the password using reversible encryption, the account properties in Active Directory Users and Computers (ADUC) may show the box checked for Store password using reversible encryptionIt looks like this:

You can use the command line to query AD for any users with the reversible encryption flag set in the UserAccountControl attribute using the following PowerShell command:

Get-ADUser  -Filter  ‘useraccountcontrol  -band  128’  -Properties useraccountcontrol  | Format-Table name, samaccountname,useraccountcontrol

If you want the excruciating detail about the syntax of this command, scroll down to the section at the bottom titled In the Weeds. Otherwise, suffice it to say that the above command will get you all the accounts that have been configured to store passwords using reversible encryption.

So the big question is why. Why would there be a need to store credentials in this manner? The answer is that some applications require it. So Microsoft has provided a mechanism for applications that need to know user password values to force storage of reversibly-encrypted passwords in order to authenticate users. The applications that I know about that require reversible encryption are MS CHAP, SASL Digest Authentication, older MacOS hosts that need to authenticate to a Windows domain. There are also very possibly other third-party apps that use it as well.

Here is a best-practice tip from Microsoft about this setting:

Take Aways

  1. Even though it requires a domain administrator to extract hashes from the Active Directory database using the method we have shown above, it implies that the DA (or a stolen DA account) could easily learn other users’ passwords. This violates the principle of non-repudiation, which prevents users from disputing activity within an information system.
  2. We often find backup sets that contain VSS snapshots providing access to the AD database. The backup sets are often accessible by lower privileged accounts and perhaps even all domain users. In that case, any domain user could easily have access to any account password that was stored using reversible encryption.

In the Weeds

I promised some more details on the command syntax shown above. As a refresher, here is the command to extract users whose passwords are stored using reversible encryption from Active Directory using PowerShell:

Get-ADUser  -Filter  ‘useraccountcontrol  -band  128’  -Properties useraccountcontrol  | Format-Table name, samaccountname,useraccountcontrol

Let’s break it down piece by piece:

Get-ADUser is a cmdlet in the ActiveDirectory PowerShell module that is installed on Windows Server 2008 R2 and later by default. It can be imported using the Import-Module command.

Filter – Uses a PowerShell expression to tell the cmdlet what the search parameters are. In this case we are searching for user accounts with specific UserAccountControl attribute values (more on that in a minute).

You could also use LDAPFilter in place of Filter. It does the same thing as Filter but uses LDAP query syntax. The correct syntax for finding the desired UserAccountControl  value would be:

Get-ADUser -LDAPFilter “(&(objectCategory=Person)(UserAccountControl:1.2.840.113556.1.4.803:=128))” -Properties useraccountcontrol | Format-Table name,samaccountname

useraccountcontrol -band 128

The UserAccountControl attribute in Active Directory is an attribute associated with settings for user accounts and is 32 bits in length. Each bit represents a specific setting regarding that user account. For example, when an account is disabled the second low-order bit is set to “1”. In the case of reversible encryption, it is the 8th low-order bit that would be set to “1”. The 8th low-order bit corresponds to the decimal value 128. (I told you we were getting into the weeds.)

To access the values for specific bits within this number, you have to use logical bit-level operations. To learn more about bitwise operations you can look here or here. In our example, -band 128means use a bitwise AND operation with the value 128 to determine if the 8th low-order bit is set or not (regardless of what other bits are set within the 32-bit number). This basically isolates just one bit and allows you to examine it like this:

If you are using the LDAPFilter, the bitwise operation is specified by using the equivalent LDAP syntax for bitwise operations, 1.2.840.113556.1.4.803. By specifying the value 128 we are requesting that all records with the 8th low-order bit set to “1” be returned.

Whew, the hard part is over. The rest of the command is really just about formatting the output.

Properties useraccountcontrol

Because the Get-ADUser command retrieves a default set of properties that does not include the UserAccountControl attribute, you have to explicitly ask for it in the results with the -Properties parameter.

Format-Table name, samaccountname,useraccountcontrol

The Format-Table command tells PowerShell how you want the output formatted along with which properties to show. You could use Format-List instead of Format-Table if you want the results listed vertically instead of in a table.

Of course, you could output it all to a file for further processing….

Get-ADUser  -Filter  ‘useraccountcontrol  -band  128’  -Properties useraccountcontrol  | Format-Table name, samaccountname,useraccountcontrol | Out-File -Encoding ascii MyOutput.txt

Bravo! You made it to the end.

Thanks for reading and, as always, if you have comments or great stories related to this topic, let us know!