From time to time we find ourselves conducting a password audit for a client. While not terribly exciting from an attackers point of view, it is a necessary check to perform and can provide valuable output if the client is capable of acting on it. Many organizations also perform similar assessments internally. Typically the process looks something like this:
1. Obtain Password Hashes:
Performing a hash dump on a domain controller can be accomplished in a number of ways, such as fgdump, or using Meterpreter’s “hashdump” command.
2. Crack the Hashes:
If you are doing this professionally, you likely have a dedicated system with several high end graphics cards. Most commonly you’ll use oclHashcat, because of its large feature set, and speed. How long you run the offline attack for can depend on several factors. The type of attack (brute force, dictionary, mask), how powerful the cracking rig is, how many hashes you are attempting to crack all play a part in how quickly you are going to get your results. Ideally, you should let the attack run for at least a week (assuming you don’t get all of the passwords before the week’s end). Obviously, the more time you can allow, the greater the results will be.
3. Analyze the Results:
Here you will want to see the results of the cracking process and analyze them for commonalities, to identify deficiencies in user passwords and areas to improve. Maybe you’ll conduct some training based on the results of the audit. For years, DigiNinja’s Pipal has been the go to tool for this analysis.
This is all fine and good, and the results provide some solid places to start improving for many organizations, however we have been noticing a different type of trend for a while now. Often times we will break into an organization through some form of password attack (guessing or brute forcing). Once we are in we are compromising passwords with Mimikatz, as well as, dumping and passing hashes. Needless to say, we are interacting with passwords a lot. When this would come up in meetings with the clients, many times they would note that one or more passwords identified didn’t meet the requirements in their password policy. Also, we still commonly see LM hashes stored for users when the client claimed to have disabled LM hashes years ago. This is a pretty good indicator that those users have not updated their passwords anytime recently. So to address these concerns we wanted a way to check passwords against requirements specified in the domain password policy.
Enter pw_audit.py (super-boring name, I know).
This is a program I wrote to provide that type of information on passwords. The idea is that the user specifies the length and complexity requirements, which default to the Microsoft standard of eight and three, respectively, as well as any additional options and the script will tell you how many passwords failed and how many met the requirements. If the “–verbose” argument is passed, the usernames associated with the passwords (failing and passing) will be returned. The output can be optionally written to a file as well. The user also has the ability to specify the delimiter used in the input file, and the script will skip any lines that have the delimiter present more than once. You may have guessed but this was implemented to prevent errors when one of the passwords includes the delimiting character.
One of the interesting options is the ability to pass in a regular expression to match passwords against. The need for this came about during a recent audit, where we discovered an alarming number of passwords fitting a very specific schema. Issues like that commonly occur when the help desk is resetting passwords to something common, and not forcing the user to update it at next login (remember folks, users won’t update their password if you don’t make them). The script is pretty straightforward, so there really isn’t too much else to say about it. I would encourage you to try it out the next time you are auditing passwords, hopefully it will add some extra value for your assessment. Below is some sample output.
As always, happy hunting!