Evidence abounds that Microsoft is bloody tired of taking the hit for all the world's security problems, and evidence of that continues to appear in new products it ships. One of the areas where it has been hit hardest is in scripting, both through email and its built-in support for scripting through the Windows Scripting Host (WSH). Far too many viruses have been unleashed through those innocent looking .vbs and .js files, but Microsoft is fighting back.
One of the major problems with securing scripts through WSH is that they need access to system and/or network resources, particularly the filesystem, to do anything useful. That's a double-edged sword, of course: anything technique used to do something good and noble with a script can be used by a vandal as well. But how do you build security into what is only a text file, after all?
The key, of course, is something that's not terribly new: digital signatures. Signing script files -- or any other resource, for that matter -- protects against two risks. The first is that you might run code from someone you don't know. Managed .Net code handles this kind of situation in clever ways, but remember that we're talking about text files. The second risk is that even if a file is provably from someone you know and trust, a bad guy might have changed what the good guy wrote, and when you execute the script you may find that your hard drive has been emailed to some unnamed country that harbors malicious hackers. WSH supports signing scripts, which helps alleviate both these risks. It's not going to end script viruses, but it's a great first step.
A signed script "guarantees" (encryption can be broken, in theory, but not easily or quickly) that the person claiming to have written the script really did, and that it hasn't been tampered with since being signed. The signing process uses the signer's certificate, the hash of the script file, and the signer's private key to create a signature in the script file. When WSH loads the file, it checks the certificate to see if its okay, and then checks to see whether the hash matches the contents of the file. If the hash is different, somebody has tampered with the file. WSH will tell you about this, and will ask whether you still want to run the file. This is still a vulnerability, since a user can decide to ignore the dire warnings and thereby unleash viruses and untold doom. If the certificate is invalid, expired, has been revoked, or isn't trusted, then WSH will notify you and will refuse to run the code. The moral is that if you're a virus author, it is probably easier to just go ahead and change a signed script file, thereby invalidating the hash, and count on hapless users blowing past the WSH warning.
Signing through WSH covers all the appropriate .vbs, .vbe, .js, .jse, and .wsf file types. For backward compatibility (and to make sure that viruses can safely spread on earlier versions of Windows), the script-signing mechanism puts the signature into comment blocks at the end of vbs and .js files and into a
Windows provides a standard mechanism for signing code via signcode.exe. Unfortunately, signcode.exe doesn't ship with Windows itself, but only with the Windows SDK. If you don't have the SDK, WSH provides an object, Scripting.Signer, that lets you write a script to sign a script. Here is a sample snippet of code I got off of MSDN that shows how it works: var Signer, File, Cert if (!(WScript.Arguments.Named.Exists("cert") && WScript.Arguments.Named.Exists("file"))) WScript.Arguments.ShowUsage(); WScript.Quit(); } Signer = new ActiveXObject("Scripting.Signer"); File = WScript.Arguments.Named("file"); Cert = WScript.Arguments.Named("cert"); Signer.SignFile(File, Cert,"my"); The script takes a filename and certificate that you want to use to sign the file, and passes it on to the SignFile method on the Signer object, and the file is signed. The signature is added to the .wsf file within the