As penetration testers, we get a lot of joy out of compromising Windows networks. They are basically our favorite targets because of how insecure they are by default. Microsoft has always favored backward compatibility over security, and while it is possible to really lock down an AD (Active Directory) environment, it takes a lot of effort. While setting up an organization’s network in the first place, many admins take the stance of, “Let’s just get it working, and then we’ll add security on afterwards.” Nine times out of ten, they never go back and enable the security features until after there is an incident.
When performing a full scope penetration test, after we’ve gathered OSINT (Open Source Intelligence) about our target, one of the first things we’ll attempt to locate are authentication points – places on the external network where an attacker can attempt to authenticate to a network resource. We love finding things like OWA (Outlook Web Access), RDP (Remote Desktop Protocol), or an RDS (Remote Desktop Services) system, because we know that they authenticate directly against AD by default, so we know that if we can find a set of credentials that is valid on one of those, we know that they’re (almost certainly) valid on systems on the internal network. Depending on what other potential vulnerabilities we’ve discovered, we might start a brute-force against one of these exposed services in order to attempt to locate a set of valid credentials. If we built a good enough list of potential usernames during the OSINT phase, this works more often than it feels like it should. Sadly, users pick bad passwords. Even if the user we compromise is not a high-privilege user, just being able to successfully authenticate to AD is enough to start gathering more information to prepare for the next phase of an attack.
Once an attacker has a set of valid AD credentials, there is a lot they can potentially do, depending on what services have been left exposed to the world. If we assume the OWA example from above, it’s possible to configure a malicious outlook rule so that when the compromised user receives an email with a specific subject, their outlook client will download and execute attacker-controlled code, remotely compromising their workstation on the internal network, and allowing the attacker to start attempting to pivot to other systems on the internal network. If we use the RDP or RDS example from above, compromising the credentials of a user who is allowed to authenticate there could grant the attacker immediate control over a system on the internal network. Similarly, if there is a VPN (Virtual Private Network) on the border of the network, if an attacker can guess one of the user’s passwords, depending on the VPN configuration, they might now be sitting on the internal network next to production servers, depending on how “flat” the organization’s network is.
In each of the examples above, we weren’t talking about some super-“leet” 0-day exploit against a network service – we’re talking about any one of the users in an organization choosing a poor password, and the larger the target company is, statistically the more likely it is that an attacker will find one and use it to compromise the network. We see weak passwords all the time. Even if the network admins do basically everything else right, their users’ poor choice of passwords is very likely the limiting factor in the network’s security. With default AD complexity settings, “Password1” is good enough to pass as “complex”. If you enable the requirement for special characters, “Password1!” is “complex”, as far as Windows is concerned. Windows doesn’t care that your password is basically just “password” with some bling on it. Linux systems have had a module called “cracklib” which has been around since ~1995, which, when a user changes their password, looks at their choice and runs it through a series of rules to find out if the password is “weak”. It tests whether the password is a common dictionary word, or just a series of sequential numbers, or any of a number of rules. It’s not perfect, but if it’s enabled, it can prevent your users from selecting some really terrible passwords. Windows systems, sadly only have the stub of such a feature available. Microsoft has given admins the option to register a password filter DLL (Dynamically Linked Library), but as far as I could find, they don’t actually provide any instruction on how to create such a password filter DLL.
Searching for a solution to this problem, I found a few potential options: Either write one yourself, (not going to happen for most small-medium sized Windows shops), purchase a subscription to a commercial password filter DLL (all of the pricing seems to be to the effect of, “please call sales”), or else put your trust in one of a few open-source AD password filters -- One of which registers an additional service on your domain controller, which at the time of writing contains an open pull request for an unquoted service path privilege escalation vulnerability, and the other which is a newer contender which checks the user's passwords against 330 million previously-compromised passwords based off a list released by Troy Hunt. I won’t link directly to either the commercial or open source options as I’ve not had the time to personally evaluate any of them, but the point here is simple: When it comes to blocking the use of weak passwords, Microsoft is essentially leaving their customers to fend for themselves.