Users go to great lengths to create crappy password patterns, but those patterns vary wildly from company to company. As an example in Tuscaloosa, I’m sure the words ‘bama’ and ‘tide’ are used in a huge percentage of passwords. When you’re conducting a password spray, it helps the red teamer a lot to know those terms in advance. As a blue teamer, we want to set up password filters that prevent the use of these key words. It can take a long time to discover those key words via a password spray, time we often don’t have. Instead, you can grab a copy of your Active Directory database and launch an offline attack against that. You won’t discover every password, but that’s not the goal here. Our goal is to find the easy passwords, and identify what makes them easy to guess.
There are a lot of tutorials out there on how to do this, but most of them take a much more difficult approach of setting up libesedb and ntdsextract. Today, Kali ships with tools onboard that work just as well. I use those tools here, and also try to provide a little more background about things. We’ll break things down into steps:
Step 1: Obtain Permission
You’re going to be effectively guessing your co-worker’s passwords here. First, you have to be responsible with the data you’re going to obtain. Just because you have a person’s password doesn’t mean you have the right to go read their email. You can expect jail time in your near future if you can’t resist that urge.
Also, get a signed authorization form from someone high-up at your organization. CTO or equivalent is best. You can start with the OWASP authorization form, or you can use the one I used for this exact excercise on Google Docs
Step 2: Grab a copy of the Active Directory database
A few things about Active Directory.
- The Active Directory database is stored in a file named
ntdis.dit. The contents of the database are encrypted with a string that is stored in the SYSTEM registry hive, so we need to grab that as well.
- The ESE database format used by Active Directory (and Exchange) is fault tolerant, mult-master, and transactional. One side effect of this is that changes to AD are not immediately written to the master
ntdis.ditfile, they’re written to
edb<hex>.log. According to Microsoft, those edb transactional files are merged back into
ntdis.dit“when there’s time”, but in my experience that usually happens on a reboot. If you’re looking at the timestamps on
C:\Windows\NTDS\and you’re seeing an older date than you want, you’re going to need to reboot your DC to force that update. I have a personal hunch that doing a “compact” operation using
ntdsutilwill accomplish the same thing, but I haven’t tried it. Let me know in the comments if this works for you.
- The database file is locked, and can’t be read from or written to directly. We’ll use a shadow copy to get what we want.
Let’s start by making a copy of the
ntdis.dit database file and the
SYSTEM registry hive file. On one of your domain controllers run this from
net start vss vssadmin create shadow /for=c: vssadmin list shadows copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\windows\ntds\ntds.dit C:\temp copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\windows\system32\config\SYSTEM C:\temp vssadmin delete shadows /For=c:
Note that if you already had some shadows of the C drive, your copy commands above should reflect the name of your most current shadow.
Step 3: Extract hashes
Take the two files you copied to
c:\temp above, and copy them over to your Kali instance. In our examples, we’re going to store everything in a directory called
As mentioned above, many other posts go into great detail on how to download and compile your own copy of libesedb and ntdsextract. Nowadays, there’s no need thanks to the authors of impacket. Run the following on your Kali instance:
cd ~/pwdump impacket-secretsdump -system SYSTEM -ntds ntds.dit -outputfile ad LOCAL
This runs the secretsdump utility from the impacket scripts. We feed it the SYSTEM hive file to retreive the encryption key from, and the ntds.dit file itself. We speficy that our output files should be prepended with ‘ad’, and that we want secretsdump to run on LOCAL files. Depending on the size of your database, within a few minutes you should have something like the following:
justintime@kali-justin:~/pwdump$ ls -al ad* -rw-r--r-- 1 justintime justintime 321896 Jul 26 09:20 ad.ntds -rw-r--r-- 1 justintime justintime 0 Jul 26 09:14 ad.ntds.cleartext -rw-r--r-- 1 justintime justintime 701618 Jul 26 09:20 ad.ntds.kerberos
The only file we’re concerned with here is
ad.ntds. It contains our users and hashes in a
pwdump format, which looks like this:
<user>:<id>:<lanman pw>:<NT pw>:comment:homedir:
Step 4: John the Ripper
To use John the Ripper, it works best to have a trusty wordlist that you can feed it. I highly recommend rockyou, you can download it from Daniel Miessler’s Github Repo or use this one-liner:
curl -L 'https://github.com/danielmiessler/SecLists/blob/master/Passwords/Leaked-Databases/rockyou.txt.tar.gz?raw=true' | tar -xzvf - > ~/pwdump/rockyou.txt
Step 4a: If you have LM Hashes, crack those first
You’re only able to complete this step if you have one or more LANMan hashes in your pwdump file. You can quickly determine this by running this command:
grep -cv aad3b435b5 ad.ntds
If that command returns anything greater than zero, you have LANMan hashes in your pwdump file, and you have a problem that you need to fix. If the command returns 0, skip to step 4b.
LANMan hashes are a problem because: 1. LANMan passwords aren’t case sensitive - everything is changed to uppercase before generating the hash 1. Password length is capped at 14 characters. This makes a cracker’s job easier. 1. Each password is broken into two halves of 7 characters each. This makes the cracker’s job exponentially easier. 1. There is no salting, meaning that if two users have the same password, their hashes will be identical.
All of these issues add up to make LANMan hashes extremely easy to crack with modern hardware. Let’s prove it!
We’re going to tell john to attack the LM hashes first, using the rockyou wordlist, and to apply it’s rules to each word. The rules tell John to apply the same tricks humans do to “obfuscate” a word into a password. Here’s the command line:
john --format=LM --wordlist=rockyou.txt --rules ad.ntdis
Depending on how many hashes you have, john should be done in less than 5 minutes. With any luck, you saw it successfully crack a few of those. You can see what it cracked by using the show option, like so:
john --format=LM --show ad.ntds | grep -v aad3b
Looking at the output for that, you’re probably saying, “what good are these passwords, they’re all uppercase, and some of them are truncated???”. Well, having those hashes cracked makes it pretty trivial to crack the case-sensitive password. We just create our own wordlist from the LM hashes, and use those to crack the NT hashes. First, create the wordlist:
john --format=LM --show ad.ntds | grep : | cut -d: -f2 | grep -e '[^\s]' > lm.txt
We’ll use that wordlist in step 4b.
Step 4b: Crack the NT Hashes
If you did step 4a above because you had LM hashes in your pwdump, let’s do a quick pass using our custom wordlist. If you don’t have LM hashes, you can skip this command:
john --format=NT --wordlist=lm.txt --rules ad.ntdis
Now, let’s take a pass using rockyou:
john --format=NT --wordlist=rockyou.txt --rules ad.ntdis
From here, it’s up to you to see how many more you can crack. You might try some other common wordlists. Crackstation’s human only list is a good smaller one. The “have I been pwned” lists are also very effective. For bonus points, you can read the manpage and do a brute-force incremental attack.
Step 5: Analyze the results
You’ll recall that our goal was to identify patterns in our users’ choices of passwords. Here’s a few ways you can slice and dice the data:
# Show any passwords occurring more than once: john --show --format=NT ad.ntds | grep : | cut -d: -f2 | grep -e '[^\s]' | sort | uniq -c | sort -rn | grep -v -e '^\s*1 ' # Lowercase everything, and show identical passwords: john --show --format=NT ad.ntds | grep : | cut -d: -f2 | grep -e '[^\s]' | tr '[:upper:]' '[:lower:]' | sort | uniq -c | sort -rn | grep -v -e '^\s*1 ' # Lowercase everything, remove numbers, and show identical passwords john --show --format=NT ad.ntds | grep : | cut -d: -f2 | grep -e '[^\s]' | tr -d '[:digit:]' | tr '[:upper:]' '[:lower:]' | sort | uniq -c | sort -rn | grep -v -e '^\s*1 ' # Sort everything in a file named sorted.txt so that you can scan through them all manually and identify patterns: john --show --format=NT ad.ntds | grep : | cut -d: -f2 | sort > sorted.txt
Step 6: Stop the bleeding
Disable LANMan hashes
You don’t need LANMan hashes. Well, you do if you’re running Windows 98 or below. If you’re running Windows 98, why are you reading a blog instead of interviewing for a new job?
Here’s Microsoft’s instructions on how to disable LM hashes. Note that for every user that had a LM hash, after you change the registry settings/group policy, you’ll need to force the user to change their password in order to update the database.
Educate your users
Find the users that had extremely weak passwords set, and help them understand why their password was easy to crack, and why that’s a big deal. Most of the time, the user thought what they were doing was the right thing to do, and when you explain to them it took you less than one hour to guess it, they’ll be more than happy to change their ways.
Conduct routine audits
You can repeat the process we’ve just done here once every N months, and that’s great. You can also become your own red team, and start using what you learned here to conduct password sprays.
Implement password filters
Microsoft gives you the ability to implement your own filtering mechanisms to prevent users from choosing passwords with certain strings in them, consider implementing that on your DC’s.
Most of us know this by now, but it needs said. Passwords are broken by their very nature, and Multi-Factor Authentication is one way to mitigate that.
In this post, we’ve outlined how to conduct an audit on your accounts in Active Directory so that you can help protect your users from activities like password spraying.