The windows scripting host (WSH) allows administrators to execute scripts to automate administrative tasks, execute network login scripts and query systems for information - just to name just a few of it’s benefits. I regularly write and run scripts; in fact I sometimes wonder how I got by before I ventured into the scripting realm. The problem with the windows scripting host however is that it can be a launch-pad for malicious code. Some administrators choose to disable the use of WSH on workstations and servers to prevent malicious code from executing. While this makes a lot of sense from a security standpoint, it severely cripples your ability to automate admin tasks, and if you’re using vbscript based login scripts then you’re going to have a real problem.
A far better approach is to use software restriction policies to dictate which scripts are permitted to run. Software restriction polices are a new feature available in Windows Server 2003 and Windows XP that are set via Group Policy. You’ll find the software restriction policy under Computer Configuration/Windows Settings/Security Settings/Software Restriction Policy.
Software restriction policies are designed to control the execution of all executables, not just scripts. There are 4 types of software restriction rules; I’m going to focus on the 3 that are beneficial to locking down the Windows scripting host. To implement the rules, you simply create them in the Additional Rules folder. Note that the folder already contains 4 default rules.

Path Rules:
Perhaps the simplest to implement, path rules let you either allow or disallow executables to run based on the path that they are launched from. For example, you could disallow the execution of .vbs files (and the various extensions associated with script files) but permit those files that are in particular network share to run.
In this Example, you would create the following rules:
Rule Type
|
Security Level
|
Value
|
| Path |
Disallowed |
*.vbs |
| Path |
Disallowed |
*.vbe |
| Path |
Disallowed |
*.js |
| Path |
Disallowed |
*.jse |
| Path |
Disallowed |
*.wsf |
| Path |
Disallowed |
*.wsh |
| Path |
Unrestricted |
\\ScriptsServer\Scripts\*.* |
You could also use path rules to disallow vbscript files from running but allow them to run from your netlogon shares so that vbscript based login scripts could run:
Rule Type
|
Security Level
|
Value
|
| Path |
Disallowed |
*.vbs |
| Path |
Disallowed |
*.vbe |
| Path |
Disallowed |
*.js |
| Path |
Disallowed |
*.jse |
| Path |
Disallowed |
*.wsf |
| Path |
Disallowed |
*.wsh |
| Path |
Unrestricted |
%logonserver%\Scripts\*.* |
Note that Microsoft’s recommendation is to avoid using environment variables where possible, as environment variables can be changed by the user to point to a different path. If you choose not to use the %logonserver% environment variable you may want to consider using your domain controllers’ names instead. This may be cumbersome if you have a large number of DCs, but you do have the ability to use wildcards in path rules, so if all of you domain controllers where named DC1 - DC100 you could implement a policy similar to the following:
Rule Type
|
Security Level
|
Value
|
| Path |
Disallowed |
*.vbs |
| Path |
Disallowed |
*.vbe |
| Path |
Disallowed |
*.js |
| Path |
Disallowed |
*.jse |
| Path |
Disallowed |
*.wsf |
| Path |
Disallowed |
*.wsh |
| Path |
Unrestricted |
\\DC*\Scripts\*.* |
I’m comfortable in using the %logonserver% variable, and would be happy to use the first example in a production environment.
Hash Rules:
Hash rules have their advantages, however for locking down WSH they don’t provide too much flexibility. Using a hash rule, you can allow or disallow the execution of files based on their content. When you create a hash rule, a “hash” of the file is calculated. Each time an executable is run, a hash of the file is compared with the hash stored in the policy. In the case of locking down WSH, you could create a path rule to disallow all vbscript files, and then create a hash rule for each script that you want to allow. While this may be suitable if you are using a single login script that rarely changes, or if you use only a handful of admin scripts that rarely change, it isn’t ideal for environments where scripts frequently change or like me you write new scripts every week. The advantage to using hash rules over path rules though is that you can modify the filename and the hash will not change. You can also run the script from any path; as long as you don’t change the actual script itself you won’t need to modify the rule.
Example of hash rule to allow approved scripts:
Rule Type
|
Security Level
|
Value
|
| Path |
Disallowed |
*.vbs |
| Path |
Disallowed |
*.vbe |
| Path |
Disallowed |
*.js |
| Path |
Disallowed |
*.jse |
| Path |
Disallowed |
*.wsf |
| Path |
Disallowed |
*.wsh |
| Hash |
Unrestricted |
SampleScript.vbs |
Certificate Rules:
Certificate rules are an excellent way to lock down WSH to only allow approved scripts to run. With a certificate rule, you import a digital certificate into a rule and then digitally sign each script that you want to approve with the same certificate. The advantage to using certificate rules over path or hash rules is that the contents, path or filename of the script can change without preventing the approved script from running.
The downside to using certificate rules is that you either need to purchase a digital certificate from a trusted public CA or install your own CA server and issue a certificate from there. In both cases, the CA needs to be defined in the ‘Trusted Root Certification Authorities’ on your workstations and servers.
Importing the certificate
Once you have obtained a certificate to sign your scripts, you need to import the certificate into the rule. This is fairly straight forward, you simply create the rule, then browse to the certificate file (*.cer, *.crt).
Signing Scripts
Strangely enough, you actually need to use a script to signs scripts. The following is an example of a script that signs the C:\Scripts\script.vbs script with a certificate called Ben Christian. The certificate must first be imported into the certificate store of the machine that you run the script on.
set objSigner = WScript.CreateObject(”Scripting.Signer”)
objSigner.SignFile “C:\Scripts\script.vbs”, “Ben Christian”
Like the other rules, to implement a certificate rule to allow signed scripts to run, you would first create path rules to prevent the various script extensions from running.
Example of a certificate rule to allow approved scripts:
Rule Type
|
Security Level
|
Value
|
| Path |
Disallowed |
*.vbs |
| Path |
Disallowed |
*.vbe |
| Path |
Disallowed |
*.js |
| Path |
Disallowed |
*.jse |
| Path |
Disallowed |
*.wsf |
| Path |
Disallowed |
*.wsh |
| Certificate |
Unrestricted |
Certificate used to Sign Scripts |
Using Certificate rules is probably the most secure way to lock down WSH with software restriction policy. If certificate rules seem too cumbersome to implement, path rules are a good way to go. In any case, implementing software restriction policies to lock down WSH on your client and server machines is better than doing nothing, and is an ideal balance between security and convenience.