| Executive Summary: |
When using the search path to resolve a command name, Windows attempts to match the command name to file-based commands in the folders in the path. If you don't specify a file extension for the command, Windows Explorer automatically searches for files with the extensions .com, .exe, .bat, or .cmd. This search process is useful but has some quirks. Applications—particularly older ones—might add their own directories to the search path, possibly ahead of Windows' intended first search folders. Malicious coders might also use pathext to make Windows identify common command names such as regedit with their application files. Tools such as Windows Vista's User Access Control (UAC) don't solve the search problem. If you're performing an administrative task and have already elevated your privileges in a subshell, invasive code will run with no special prompting. However, on systems that don't need significant command-search customization, you can do some tweaking to make it very difficult for an attacker to use command search to escalate privileges. The tweaking simply involves locking down the search path wherever possible, modifying and locking down the pathext variable, and maintaining security for the folders used in the search process.
The Windows search path represents a significant potential vulnerability on many systems. I'll explain why, then show you how you can minimize the vulnerability by identifying machines that don't need modified command search and locking them down.
Understanding the Search Path
When you run a command in Windows by specifying simply the name of the application—not its complete path—Windows has to search for the application. Windows Explorer, cmd.exe, and Windows PowerShell all have their own methods of attempting to resolve names before performing a search, but eventually they fall back on using the process environment to search for the command. Other shells might use the path and pathext variables to find the command.
The path variable is merely a list of complete paths to particular folders, each separated by a semicolon. When you open a command-prompt window and enter the command path, you get a list that looks like this on a freshly installed Windows system:
When using the search path to resolve a command name, Windows attempts to match the command name to file-based commands in each of these folders in turn. If you don't specify a file extension for the command, Windows Explorer automatically searches for files with the extensions .com, .exe, .bat, or .cmd.
The cmd.exe shell instead uses the set of extensions in the environment variable pathext. The default value for pathext on a freshly installed Windows system is .com; .exe; .bat; .cmd; .vbs; .vbe; .js; .jse; .wsf; .wsh; .msc. So, for example, if cmd.exe is searching for a command named foo, cmd.exe first checks for C:\Windows\system32\foo.com; then C:\Windows\system32\foo.exe; and so on through C:\Windows\system32\foo.msc. If cmd.exe doesn't find the command, the same process continues with the folder C:\Windows and then C:\Windows\System32\Wbem.
This search process is useful but has some quirks. Applications— particularly older ones—might add their own directories to the search path, possibly ahead of Windows' intended first search folders. Malicious coders might also use pathext to make Windows identify common command names such as regedit with their application files. For example, Windows identifies a file named regedit.com in the System32 folder as the command regedit because the .com extension has precedence over .exe. Even legitimate applications can cause unintended complications due to collisions in application or DLL names.
Tools such as Windows Vista's User Access Control (UAC) don't solve the search problem. If you're performing an administrative task and have already elevated your privileges in a subshell, invasive code will run with no special prompting.
In short, if someone is able to compromise your system by putting malicious files on it, the Windows search process offers the attacker several attractive paths for escalating the compromise into system control. However, on systems that don't need significant command-search customization, you can do some tweaking to make it very difficult for an attacker to use command search to escalate privileges. The tweaking simply involves locking down the search path wherever possible, modifying and locking down the pathext variable, and maintaining security for the folders used in the search process.
Finding Systems You Can Lock Down
The first step is to determine the current details of the command-search process on client systems. The simplest general technique is to collect information about the path and pathext variables on every system on the network.
If you have familiar registry auditing tools available, you can use them to check the path and pathext value names in the Environment registry subkey, located in the registry path HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment. If you don't have such tools available, you can use the CheckCommandSearch script, one of several scripts that I've included with this article. To get the scripts and the downloadable general Group Policy template I created, click the Download the Code Here button at the top of this page (http://www.securityprovip.com/articles/articleid/98761/98761.html). To use the CheckCommandSearch script, you need to be able to access Windows Management Instrumentation (WMI) remotely on the machines you wish to audit.
The CheckCommandSearch.cmd script is a wrapper for CheckCommandSearch.vbs that ensures that CheckCommandSearch.vbs runs correctly within a command shell. Simply save the scripts to a folder. Create a file containing the names of computers you wish to check remotely, one name per line, and save it. Assuming you've saved the computer listing as computers.txt in the same folder as the scripts, just open a command-prompt window, change to the directory where you saved the scripts, and use this command:
CheckCommandSearch < computers.txt
You can redirect output from the command to a file named CommandSearch.txt like this:
CheckCommandSearch < computers.txt >
If the script can’t connect to a remote system, you'll see an error message similar to the following onscreen (even if you redirected output to a file): SomeServer: Error: could not connect to remote system.
CheckCommandSearch remotely checks the path and pathext values on each system. If it gets values back, it removes elements that match the defaults for path and pathext, then concatenates any leftover values and emits them on a single line, separated by a tab. If you checked a remote system named Server1 that had both PowerShell and Perl installed, for example, you would see output that looks similar to that shown in Figure 1. Values won’t line up cleanly on the screen, but a spreadsheet program such as Microsoft Excel can easily import the tab-delimited values into a readable table.
Besides quickly collecting data for several systems, one advantage of this script is that by removing the default search folders and searched extensions, you can more easily see what is unique to your LAN. You'll see that computers with standard search paths and extensions show no values next to their names. You'll be able to lock down the path variable of computers with no search path elements shown, with no loss in functionality, and you'll be able to lock down pathext on computers with no pathext elements. It's also worthwhile to investigate the machines that do show some unique elements; in many cases, the custom path or pathext elements might play no useful role.
Creating and Implementing Standard GPOs
The next step is to implement a standard set of policies for machines that need similar command-search configurations. The simplest solution for mass deployment is a custom Group Policy template providing drop-down item lists for each discrete configuration you need to apply to particular groups.
The downloadable Command Search Policy.adm file is a general Group Policy template that provides preconfigured policies for command search that you can apply to your LAN. It includes two possible choices for preconfigured path variables that you can apply to systems. The default Windows search path is the default and will show up in the Group Policy Editor (GPE) with the name Default Path. There’s also a custom configuration named IT Support that includes support for systems that have Windows PowerShell installed. Each configuration consists of the keyword NAME followed by the name that will be displayed in GPE for the policy; the optional keyword VALUE followed by the actual value that this option sets in the registry; and finally by the optional DEFAULT keyword indicating the default option that will be selected if this policy is enabled.
The template also includes options for enforced pathext values. The default choice in this template is a pathext value of .exe; .com; .bat; .cmd; .vbs; .js; .wsf; .wsh; .msc. This default differs in two minor ways from the Windows defaults. The first is that it assigns the .exe extension a higher priority than the .com extension. Since .exe has higher precedence, if you invoke regedit by name from a command prompt, a spoofing application named regedit.com in the same folder as regedit.exe will no longer be able to intercept the command. The second change is that I removed the .vbe and .jse extensions used for encoded VBScript and JScript files. Standard Windows tools don’t use the .vbe and .jse extensions, and administrators only rarely use them. These extensions have occasionally been popular for malicious scripts because the encoding makes it impossible to read a script without running a decoder on it first. Note, however, that I'm not turning off these extensions because they're particularly vulnerable to exploitation—they're no more vulnerable than any other extension. Removing the extensions is analogous to disabling an unused service or user account on a system.
Using Security Templates for Folders in the Search Path
The final step to improving command-search security is to ensure security on folders in the search path. The simplest way to secure the standard search path folders is to reapply default secure workstation and server security templates to systems you administer; this locks down the Windows directory and its subdirectories, preventing non-privileged accounts from saving files in those locations.
If you want to protect another folder in user paths, you need to create your own custom security template. If you haven't done this before, you might want to look at "Security Templates Define and Enforce the Rules" (http://windowsitpro.com/article/articleid/23375/security-templates-define-and-enforce-the-rules.html). In general, full control over folders in the search path should belong only to administrators, the local system account, and creator/owners. Other users will typically need read/execute/traversal permissions. After you create the template and apply it to a test system, make sure you log on as a user and test all applications that are affected by file system permissions you've restricted.
You can, of course, use security templates on systems on which you aren’t controlling the path and pathext variables with Group Policy. Using security templates lets you provide a measure of protection for specialty applications that might appear on only a few systems on your network, where path search needs more complexity than you can easily control with Group Policy. Although it's a little messy, you can even use a single generic security template to force a lockdown on all folders that appear in paths on any machines on your network. For example, if you secure C:\Python and C:\Tcl in a template and then apply the template to machines on which one or both of those folders is missing, you'll simply get warnings logged about the missing folders.
Understanding Search Path Control Effects and Limitations
Controlling the search path isn’t a front-line security measure. Instead, it helps prevent privilege escalation if a malicious user does successfully gain access to your network. Intercepting a trusted application using path search is an attractive strategy for newer exploits trying to get past UAC. Tighter path control not only provides you a second line of defense against such external threats but also makes malicious hacks by trusted internal users more difficult.