This blog entry is intended to document a technical procedure used to perform a password audit. This is mostly intended for future use by security analysts who may be called on to perform a password audit, but is published here for the benefit of those who want to know the details of how the procedure works. There is an argument that this sort of thing should remain secret, but there is nothing within this blog entry that is any way secret – all of the tools are publicly available, etc. It isn’t secret!
As a reminder, this procedure should only be carried out after going through the formal change process and only by suitably qualified IS staff.
Password auditing asks a different question to ordinary password cracking. In the later, we want to know what the password is (and what username it applies to). In the later, we want to know two things :-
- Is the password weak?
- Does the password conform to existing password policies.
In neither case do we need to know what the password is … indeed there would be certain advantages to a tool that does not tell us what the password is. However whilst using a password cracking tool intended to disclose passwords for the benefit of an attacker does have certain advantages … it tests whether a password is weak using the methods an attacker would use. As an example, the password “Password1” may meet some password policy requirements (although not ours), but is one of the simplest passwords to crack because it is well known.
One of the most widely used tools out there is called John the Ripper, and so that is the tool selected for use (the fact that it is a Unix tool used from the command-line is a happy coincidence).
In summary the procedure for password auditing is :-
- Copy the master “password” files (containing the password hashes) somewhere where they can be analysed.
- Extract the relevant information from the copied “password” files in a form that can be used by the tools.
- Run a well-known password cracker on the result.
- Extract the usernames from the result, and send each one a notification (via email) that their password has been found to be weak.
Copying The Active Directory Files
- Login to one of the ActiveDirectory servers with appropriate privileges, and open a command window.
- Create a snapshot of AD (See http://technet.microsoft.com/en-us/library/cc753609%28WS.10%29.aspx) :-
ntdsutil > snapshot > activate instance ntds > create {Copy the GUID that gets printed} > list all > mount 1 (if the relevant snapshot is #1)
- Open a new command window (you will need to right-click and “Run as Administrator”) and use it to go to the snapshot :-
cd \$SNAP* cd Windows cd NTDS copy ntds.dit \
- Whilst the snapshot is available, also copy the “system hive” :-
cd .. cd system32 cd config copy SYSTEM \
- Go back to the ntdsutil command and remove the snapshot :-
> list all > unmount 1 > delete 1
- Copy c:\ntds.dit & c:\system somewhere where it can be worked on. Once copied the original copies should be removed.
Extracting and Formatting The Data
Before the ntds.dit file can be processed by John the Ripper, it needs to be “massaged” into an appropriate format. This is a two step process.
First of all, use esedbexport (see http://code.google.com/p/libesedb/ for the package that provides this command) to extract the data into separate files in a sub-directory :-
esedbexport -l esed.log -t myw2008-server.ntds.export myw2008-server.ntds.dit
Next run the dsusers.py script (see http://www.ntdsxtract.com/ for the package that provides this script) to generate something readable :-
python2 dsusers.py \ ${PATH-TO-EXPORTED-NTDS}/datatable.3 \ ${PATH-TO-EXPORTED-NTDS}/link_table.5 \ --passwordhashes ${SYSTEM-file} > raw.out
The file raw.dat contains the password hashes. It can either be edited normally to pull out the relevant lines, or running the following script will do the same (with a lot less pain for a file that may contain many thousands of accounts) :-
#!/usr/bin/perl use strict; use warnings; my $sam; while (<>) { if (/SAM Account name: (.*)$/) { $sam = $1; $sam =~ s/^\s*//; } if (/^Password hashes:/../^$/) { next if /^Password hashes:/ || /^$/; s/^\s*//; if (defined($sam)) { s/^[0-9A-Za-z .-]*:/$sam:/; undef $sam; } print ; } }
The result can be passed into John …
Running John The Ripper
Normally you could simply run John the Ripper on the final result of the last two steps and it would merrily start attacking the passwords. However we have rather specialist requirements and want John the Ripper to perform two distinct tasks :-
- Run through a dictionary of words with word-mangling rules.
- Run through a brute-force password crack of all passwords of 6 characters or less.
[Incremental:All6] .include [Incremental:All] MaxLen = 6
In some cases, this may include a MinLen directive limiting the checking of All6 to only 6 character passwords.
This requires two invocations :-
john --session=Audit-W --format=nt2 --wordlist=all.lst --rules \ password-file.txt john --session=Audit-I --format=nt2 --incremental:All6 \ password-file.txt
This will take quite a while to run. The suggestion is to start this on a Friday and leave this running all weekend.
The final result can be shown with john -show password-file.txt.