- API Penetration Testing

How to perform Password Spraying on your AD before attackers do

That's a guest post from our friend - Artem Ageyev, a seasoned infosec expert with decade of experience managing cybersecurity of high-profile Belgian, Japanese and Russian companies.
User asking customer support on security of his password
If your company actively uses a Windows domain, sooner or later, you will acknowledge the need for password security. There are no standard tools (except for the trivial group password policy); there are no commercial products either. Passwords are stored in hashes, which are also quite challenging to obtain, so direct security analysis is impossible.

I tried to build a process that, with the right skill, will not take you more than a few hours and will be perfectly repeatable. It will be possible to directly track how your efforts increase the company's passwords strength, which is always a pleasure.

Kinds of password attacks

A service for checking leaked passwords
We can split password attacks into two large groups: online and offline.

If an attacker managed to obtain password hashes, he could use an offline brute-force attack. I must say that if an attacker was able to get an NT hash on the corporate network, something has already gone wrong. Perhaps you have more significant problems than hash strength. Thus, brute-force protection is mainly a developer's business: you need to choose the correct (slow) hashing algorithms. Therefore, I usually leave brute-force out of the research scope.

In the online attacks category, we have password spray and password replay.

According to Microsoft data, password spraying is the most common password attack, responsible for ~ 40% of successful hacking of O365 accounts. Attackers try the same password on several thousands of AD accounts at once. Password spraying provides a high speed of brute force, while the account lockout policy does not work if the wrong password is entered multiple times.

Password replay is the second most frequent attack. Attackers are using databases of leaked accounts by trying them on your systems. If an employee uses the same password that his LinkedIn account had in 2012, the doors are open.

The average user remembers eight different passwords but uses more than 40 accounts (including personal); therefore, passwords are reused. The task of corporate information security is to convince the user to allocate precious space in his memory for a unique password for the corporate account. The most expensive memory in IT is user memory. Password reuse is indeed the problem of our time.

You can check your password for the presence/absence of leaks here (but better not, or get ready for a nasty surprise).

What passwords are able to withstand hackers?

Password compexity requirements
Now we have basic requirements for corporate passwords:

  • Password should not be part of any known data leak.
  • Password must be unique.
By the way, these are the only requirements that make sense for passwords. If you still need to change your password or the presence of special characters periodically — read the Microsoft recommendations on passwords. "Memorability" of a password is no less critical than special characters or leapfrog with its change.

Both of these requirements are easy enough to test without any significant investment of time and resources, and I'll show you how.

A Workflow for Password Spraying

1. Getting hashes

Any domain controller stores hashes in the ntds.dit file. The encryption keys required to extract the hashes are stored in the SYSTEM branch of the domain controller's registry.

To extract ntds.dit, you need to do the following:
  • Open the PowerShell console on the domain controller
  • Create a shadow copy using the command below:
vssadmin.exe create shadow /for=C:
selecting NTDS folder
  • Enter the Windows folder and select "Properties" for the NTDS folder:
shadow copy
  • Copy the shadow copy from the "Previous versions" tab:
  • Delete the shadow copy (not necessary):
Vssadmin.exe list shadows
Vssadmin.exe delete shadows /shadow="<shadow copy ID here>"

Now you need to copy the SYSTEM branch of the domain controller register:

That's it. You need the domain controller no longer. By the way, if by that moment you have not received a single alert from your cybersecurity tools — well, it's time for you to look for a good EDR solution.

It makes sense to carry out all further operations on a separate system, which can be disconnected from the network and then wholly cleaned—the NTDS.DIT + SYSTEM file are essentially the keys to your domain. Do not store them on your work computer.

I'm already used to working in WSL (Windows Subsystem for Linux, Ubuntu built into the Windows 10 console). Therefore, the first step is to install WSL (manually or through the app store) and RSAT (includes a PowerShell module for working with the domain) for your Windows 10 version.

Install Python 3 and the impacket hacker utility. It is needed to extract NTLM hashes from the ntds.dit

Launch WSL from the PowerShell console with the bash command:
sudo apt install python3
sudo apt install python3-pip
python3 -m pip install impacket

From the impacket package, we need the file. It can be found inside the Python module or downloaded from GitHub:
tar -xvzf impacket-0.9.22.tar.gz
cd impacket-0.9.22/examples

Extract the hashes:
python3 -system /mnt/c/Temp/SYSTEM -ntds /mnt/c/Temp/ntds.dit LOCAL -outputfile /mnt/c/Temp/hashes.lst

We should immediately check the presence and content of the hashes.lst.ntds.cleartext file. These are passwords from accounts with a "Store password using reversible encryption" checkbox in the properties. It is worth checking whether this is a necessity.

There is a lot of garbage in the file. You can remove waste like this:
cat hashes.lst.ntds | cut -d":" -f 1,4 | sort > hashes_sorted.lst

You will get a list of such kind:

Let's take another look at the source file for a second. Each account has two hashes - LM and NTLM. Instead of the first LM hash, you should see "aad3b435b51404eeaad3b435b51404ee" everywhere. If there is something else there, we can stop the audit and reallocate our efforts to the domain upgrade.

2. Favourite passwords attack

From this point onwards, I prefer to work in Excel. Here is my file template, although, of course, it's challenging to figure it out without my prompts and hints, so you will probably have to create your own.

The first thing I usually do is look for accounts with the same hash (i.e. those accounts that use the same password). If the same hash occurs more than two times, the password will have to be changed.

But before that, it's still worth filtering out inactive accounts. To do this, you can use the Get-ADUser cmdlet, which is a part of RSAT. I import the result into my Excel file. You can immediately collect email addresses — you will need them in the future to send out password reset alerts. In some companies, old accounts are not turned off but have an "ExpirationDate" set. It's better not to do this, but I collect this data too.

Get-ADUser -Filter * -Properties mail, AccountExpirationDate | Where { $_.Enabled -eq $True} | Select Name,samaccountname,mail,AccountExpirationDate | Export-csv C:\Temp\enabled_accounts.csv -NoTypeInformation

I have done half of the work — you get a list of active accounts & email addresses of your Windows Directory domain users who set the same passwords everywhere.

3. Weak passwords attack

Now let's take a look at which of our passwords the bad guys know. Because we are playing for defence — we will not try to find these hashes (this requires lots of time and excellent hardware). We will simply compare our hashes with the public database of leaked hashes courtesy of Troy Hunt.
If any of our hashes are in this database, it means it was "leaked", and we will call the corresponding password weak. Our goal is to force users to use a unique password for their work account.

Download and unpack the database (as of February 2021, it is ~ 22 GB, but it is constantly growing). The first thing to do is to convert all the hashes to low case and get rid of the counter (i.e. what was 0717B19E4348445872D8BB57D5E562B7: 14, will become 0717b19e4348445872d8bb57d5e562b7). This is done with the following command:
cat pwned-passwords-ntlm-ordered-by-hash-v7.txt | cut -d":" -f 1 | awk '{print tolower($0)}' > hash_db.lst

In 5-7 minutes, you should get a sorted hash file dump in the required format.
From this dump, you also need to leave only sorted unique hashes:
cat hashes_sorted.lst | cut -d":" -f 2 | sort -u > hashes_only_sorted.lst

Now we need to compare two arrays of hashes, one of which is ~ 20 GB.

On my laptop, this turned out to be an overwhelming task. Python ate all the memory and did nothing. Then I had to split hash_db into 3-5 GB pieces, and things got off the ground.

Thus, the algorithm looks like this now: we split a 20 GB file into 3-5 GB pieces (multiples of 33 bytes so that all hashes remain intact). We compare each piece in pairs with the array of hashes from the dump using the Python set.intersection. The output will be a file with the intersection of the sets of hashes from the dump and leaked passwords database.

We can see a small python script that does all of the above here.

It takes 5-20 minutes on an average computer. It is possible, of course, to optimise it, but why? Just enjoy making a cup of tea or coffee and a sandwich while the script works.

I take the resulting file into my excel and filter it by the enabled_account flag. For clarity, I take a few of the company's popular leaked hashes and transform them into passwords through sites like or It is for illustration purposes only but is not the whole projects' goal. We are good guys, and hashes are good enough for us.

The second half is also ready. Now the fun begins.

4. Metrics

If we take a close look at the resulting file, we will see an excellent KPI for the Information Security department — the percentage of accounts with a strong password. Calculating this KPI is simple:

P = 1 - enabled_accounts_with_weak_password / total_enabled_accounts

There enabled_accounts_with_weak_password are active accounts. The actual password of which quals to many leaked or repeated passwords.

The information security department's task is to ensure that this percentage grows steadily to some like 95%.

I also consider another indicator - the number of users who changed one weak password to another weak password after a warning from the information security service. Users are the audience you need to work with. We agreed on three notifications within the company, and if it didn't help - assign to the user a talk with HR.
Before starting the audit, you need to prepare materials to raise user awareness. Otherwise, the meaning of the whole undertaking will be nil.

Prepare a page describing how to choose the right password. It would be nice to hang posters around the office (here's an example of free ones) and make a thematic corporate mailing list. An important step is to schedule meetings with IT technical support and convince them of the importance of choosing good passwords, first of all. Usually, the most repeated password in a company is the one helpdesk assigns to new accounts by default.

The hardest part is the service accounts. Contractors usually create them, and the password "India12345" with the checkbox "never expires" is shared here. You need to carefully change such passwords because only nobody knows where they're used in a production environment.

If you manage the information security dept load and direction right, only monitoring will fall on the blue team's shoulders. The hardest part will go to IT.

I look forward to your comments and questions.
Artem Ageyev
Nyrstar, Information security manager