Petya: disabling remote execution of psexec

This morning in response to reports of an outbreak of yet more malware I wrote a quick blog post on one way to stop the SysInternals psexec from being allowed to execute by using the Image File Execution Options registry key mechanism – see here for that post.

My technique was, and still is sound, but @RennJohnny correctly pointed out that if the psxec.exe executable was renamed then my approach would not work. I therefore set about finding another way to stop psexec from running for those who don’t (yet) have security software in place to stop the exploit. Note that you need to be running it on a system where you are an administrator and have the same rights on the remote system to be attacked. As the disposable virtual machine that I used for my testing is not on a domain, I passed explicit credentials to psexec for my testing – I don’t believe Petya operates this way but my solution will still work.

So when psexec is used to run something on a remote system, it works by creating a new service executable called psexesvc.exe which is embedded within the original psexec.exe file. This is copied to the Windows folder on the remote machine via the admin$ default share (hence why you need to be an admin to get psexec to work remotely). It then creates the PSEXESVC service with this, now local, executable, starts it and then runs the specified command.

What I found was that even when I copied psexec.exe to another file name, the file produced and copied to the remote system was still called psexesvc.exe. This is what happens when you run the copied psexec.exe and tell it to invoke a command on a remote machine:

psexesvc allowed

 

On that remote system we can then see this has been created in the services registry key:

psexesvc registry

How do we stop it? I reckon that the easiest way is to use good old Image File Execution Options (IFEO) mechanism again but this time we create the key “HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\PSEXESVC.exe” and in there create the REG_SZ value called “Debugger” and set it to “svchost.exe”. Now when we try and run psexec to execute on the system where we just patched the registry, this happens instead:

psexesvc blocked

What happened? Well when the Service Control Manager (SCM) on the remote machine was asked to start the PSEXESVC service, it started the psexesvc.exe process but the IFEO entry we created caused it to run svchost.exe instead but as that can’t be used as a standalone service, it failed to start so SCM reported this to psexec which is the error we see above. You will also get this in the System event log of the remote system:

psexesvc eventlog.PNG

One way to roll it out to all your computers is to put the above registry value into a Group Policy Preference that applies to those computers.

You can also create a dummy psexesvc.exe file in your Windows folder, remove all permissions and change the owner to, say, TrustedInstaller, and that will also prevent it from running.

I hope this helps some of you and stay safe (and don’t run routinely with admin privileges!).

Petya: easily disabling access to psexec

So it seems there is yet another piece of ransomware in the wild which is more sophisticated than Wannacry as it uses multiple attack vectors. I have read that one of these is once a machine is infected that it uses the great SysInternals utility psexec.exe, and possibly Microsoft’s command line WMI utility wmic.exe, to spread further. Whilst there are products, like Ivanti Application Control, formerly AppSense Application Manager, that can be used to blacklist these, if you haven’t got those products today then you need a way of stopping these attack vectors. One way would obviously be to delete wmic.exe, or remove NTFS permissions to it, but you can’t do that for psexec since presumably the malware is either downloading it or has it embedded within its payload.

Here is where we can use the little known Image File Execution Options (IFEO) registry key to put a temporary, or permanent, block on these, or any other executables, so they cannot run. We can either get them to fail silently or run a script informing the users that their machine is infected.

IFEO has been around for 20+ years – in fact the very first version of the software that I wrote that became AppSense Application Manager used this feature. It is great for debugging but is also an attack vector itself for malware as it can be used to disable security programs with the same technique. One mitigating factor is that because the key is in HKLM, you need administrative rights to write to it and we don’t let any user run with administrative rights when they are running web browsers, email, Office products, etc. now do we?

So what do I do? In its simplest form, create the key “psexec.exe” in “HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options” and then create a REG_SZ value called “Debugger” and set it to “svchost.exe” as below:

ifeo psexec

Job done! If you run psexec.exe before adding the above settings you’ll see something like this:

psexec before

But once the registry key and value are in place we get this instead:

psexec after

Attack vector thwarted! But aren’t we then running a service because svchost.exe is being run instead? No, service executables can’t just be run from the command line, they need to be invoked via the Service Control Manager (SCM), so this invocation of svchost.exe just fails silently.

Do the same with a wmic.exe key and that’s both supposed attack vectors blocked for now.

You can also set the value to run a script although you need to ensure that the script itself cannot be compromised using file system security. For instance, if I set the Debugger value to this:

"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -file c:\temp\infected.ps1

Note the use of the full path so we don’t accidentally run a malicious powershell.exe (unless your whole system is compromise!) and if using PowerShell rather than cmd.exe ensure that your PowerShell execution policy allows the script to run.

My c:\temp\infected.ps1 script contains just  this:

$null = [System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic')

$null = [Microsoft.VisualBasic.Interaction]::MsgBox( "Your system is infected - call IT now!" , 'OkOnly,SystemModal,Critical' , $MyInvocation.MyCommand.Name )

then when psexec is run a user will get this popup:

infected

How do I roll this out quickly in an enterprise? Unless you’ve already got something that can push out registry settings to multiple computers then I would suggest that Group Policy Preferences is one of the easiest ways of achieving this.

When your security software is up to date then you might want to delete the key/value unless you need to run psexec.exe for other reasons (it is a great tool and I hope it isn’t blocked by anti-virus software in the future).

It may also be worth changing the permissions on the sethc.exe (and wmic.exe) keys you create such that they are read-only to everyone, admins included, just in case further malware tries to target these keys. In fact, why not protect the whole IFEO key, particularly if you are letting people logon with administrative rights?

I  hope this helps and stay safe people!

Vulnerability when using shared Windows base user profiles

In many Terminal Services/Remote Desktop and Citrix XenApp envrionments, a common practice is to use a single shared base profile for the users, typically a mandatory profile. Since there is effectively a single copy of this profile, the registry hive contained therein, either in an ntuser.man or ntuser.dat file, must have registry permissions such that the user whose profile gets built on top of this base has full access to it. However, since it is shared across many different users, it has to have a fairly lax set of permissions – typically allowing a group such as “Everyone” to have Full Control which is then propagated to each user’s individual profile as they logon.

What does this actually mean then when two or more users are logged on to the same server at the same time? Well one user can access, and change, another user’s HKEY_CURRENT_USER (HKCU) key via HKEY_USERS\<sid>. As a demonstration, see below where user gl-test02 has accessed the registry for user gl-test01 without even having to know any SIDs:

cross user profile

You might counter that registry editing tools are disabled through group policy but unless you are running something like AppSense Application Manager to give an extra layer of security via it’s Trusted Ownership feature, then a “policy proof” version is easy to produce with a binary editor and a little know how (a useful tool for troubleshooting in “locked down” environments). Even with an extra security layer in place, it is still relatively easy to access the registry via macros in any Microsoft Office product.

Being the responsible chap that I am, I wouldn’t write about a vulnerability without also offering a method of fixing it. All we need to do is to change the registry permissions at logon such that the group ACE (Access Control Entry) with Full Control is removed and replaced with one for the logging on user. I would normally use the Microsoft subinacl.exe utility but I couldn’t seem to get it to work on HKCU so I switched to setacl.exe from Helge Klein available here. I find the syntax a little perverse but it does the job so one shouldn’t grumble in what is a very flexible and granular free tool. Add the following line into a logon script, AppSense Environment Manager logon action, or similar, assuming you have the Everyone Full Control ACE in the base profile and your HKCU is secured:

 

setacl -on hkcu -ot reg -actn trustee 
-trst "n1:everyone;n2:%username%;ta:repltrst;w:d"

This only changes the top level key but as long as inheritance for subkeys is on then this should be enough and is very quick. This then means we get this after logon if we try the same method as above to access gl-test01’s registry hive from gl-test02’s session:

secured hkcu

Note that when running setacl you will probably see the following warnings, since it is hopefully being run as a non-administrative user who doesn’t have these privileges but also doesn’t need them for this particular use of setacl.

Privilege 'Restore files and directories' could not be enabled. 
SetACL's powers are restricted. Better run SetACL with admin rights.
Privilege 'Take ownership of files or other objects' could not be enabled. 
SetACL's powers are restricted. Better run SetACL with admin rights.

The mitigating circumstances here are that the information contained within the registry is probably not that sensitive, although there may be third party products that store passwords which could be used nefariously or even just lists of document names worked on which might interest someone.