Why Won t My Scripts Run?


Why Won't My Scripts Run?

The first thing you may notice is that files having a .ps1 filename extension don't do anything automatically when double-clicked. The PowerShell window might not even open, since by default the .ps1 filename extension is associated with Notepad! But even if you manually open PowerShell and type a script name, it doesn't run. What good is PowerShell if it can't run scripts?

When Scripts Don't Run

There are two reasons why a PowerShell script might not run. The first is the script's location. PowerShell won't run scripts that are located in the current directory-it's as if it simply can't see them. For example, we created a script named Test.ps1 in a folder named C:\Test. With PowerShell set to that folder, we type the script name- it isn't found:

 PS C:\test> test 'test' is not recognized as a Cmdlet, function, operable program, or script file. At line:1 char:4 + test <<<< PS C:\test> 

This is a security precaution to help prevent a malicious script from intercepting cmdlet and command names, and then running. In other words, if we named our script Dir.ps1, it still wouldn't run-the Dir command would run instead. So, the only way to run a script is to explicitly refer to that folder:

 PS C:\test> cd .. PS C:\> test\test Ok PS C:\> 

By moving up to the C:\ folder on the first line, we are able to run the script by referring to its folder (test) and filename (test, or test\test for the complete relative path).

Actually, you can have PowerShell execute scripts in the same directory if you specify the directory. For example, running .\test.ps1 will run the Test.ps1 script in the current directory, which is specified by the .\part. However, by specifying a directory you're eliminating the possibility of your script being confused for a command or cmdlet, which makes it safe.

The second reason is the most likely reason your script won't run - the execution policy. For security purposes, PowerShell defaults to a very restrictive execution policy that says the shell can only be used interactively, which occurs when you type in commands directly and have them execute immediately. This helps ensure that PowerShell can't be used to run script-based viruses by default. In order to run scripts, you'll need to change PowerShell to a different execution policy. However, first we need to talk a bit about how PowerShell identifies and decides whether to trust scripts.

Note 

When considering security issues, keep in mind that PowerShell may eventually be a core part of Windows included with new installations.

Digital Signatures

Digital signatures are an important part of how PowerShell's security works. A digital signature is created by using a code-signing certificate, sometimes referred to as a "Class 3" digital certificate or an Authenticode certificate, which is a Microsoft brand name. These certificates are sold by commercial certification authorities (CAs). The certificates can also be issued by company's own private CAs.

The CA is where the trust process starts. All Windows computers have a list of trusted root CAs that is configured in the Internet Options control panel applet as shown in Figure 3-1. To access this window, open Internet Options, and click Publishers on the Content tab. Then, select the Trusted Root Certification Authorities tab. This list, which is pre-populated by Microsoft and can be customized by administrators, determines the CAs that your computer trusts. By definition, your computer will trust any certificates issued by these CAs or any lower-level CA that a trusted CA has authorized. For example, if you trust CA 1, and they authorize CA 2 to issue certificates, then you'll trust certificates issued by CA 1 and by CA 2-your trust of CA 2 comes because it was authorized by the trusted CA 1.

image from book
Figure 3-1: Trusted Root Certification Authorities in Windows

When a CA issues a code-signing certificate, it consists of two halves: 1) a private key; 2) a public key. You usually install the entire certificate on your local computer and use it to digitally sign code including PowerShell scripts. A digital signature is created by calculating a cryptographic hash, which is a kind of complex checksum, on the script's contents. The hash is the result of a complex mathematical algorithm that is designed so no two different scripts can ever produce the same hash value. In other words, the hash acts as a sort of electronic fingerprint for your script. The hash is then encrypted using your certificate's private key. This encrypted hash, which is referred to as the signature, is appended to the script.

Because the hash portion of the digital signature is unique to your script, it will change if your script changes in the slightest. Even an extra blank line somewhere in your script will invalidate the old checksum and digital signature. After making any changes to your script, you'll need to re-sign it. Tools like SAPIEN PrimalScript can be configured to automatically sign scripts each time they're saved, which can save you a lot of hassle.

Trusted Scripts

When PowerShell tries to run a script, it first looks for a signature. If it doesn't find one, then the script is considered untrusted. If PowerShell does find a signature, it looks at the unencrypted part of the signature that contains information about the author of the script. PowerShell uses this information to retrieve the author's public key, which is always available from the CA that issued the code-signing certificate that was used to sign the script. If the CA isn't trusted, then the script isn't trusted. In this case, PowerShell doesn't do anything else with the script or signature.

If the CA is trusted, and PowerShell is able to retrieve the public key, then PowerShell tries to decrypt the signature using that public key. If it's unsuccessful, then the signature isn't valid, and the script is untrusted. If the signature can be decrypted, then PowerShell knows the script is conditionally trusted, which means it's been digitally signed by a trusted certificate issued by a trusted CA. Finally, PowerShell computes the same hash on the script to sees if it matches the previously encrypted hash from the signature. If the two match, then PowerShell knows the script hasn't been modified since it was signed, and the script is fully trusted. If the hashes do not match, then the script has been modified, and the script is untrusted because the signature is "broken."

PowerShell uses the script's status as trusted or untrusted to decide whether or not the script can be executed in accordance with its current execution policy.

Execution Policies

Within PowerShell, you can run help about_signing to learn more about PowerShell's four execution policies that are listed below.

  • Restricted. This is the default policy. The restricted mode means that no scripts are executed, whether signed or not.

  • AllSigned. In this mode, PowerShell executes scripts that are trusted, which means they must be properly signed. Malicious scripts can execute, but you can use their signature to track down the author.

  • RemoteSigned. In this mode, PowerShell will run local scripts without them being signed. Remote scripts that are downloaded through Microsoft Outlook, Internet Explorer, and so forth must be trusted in order to run.

  • Unrestricted. PowerShell runs all scripts, whether signed or not. Downloaded scripts will prompt before executing to be sure you really want to run them.

We highly recommend that you sign your scripts since it creates a more secure and trustworthy environment. If you to plan to sign your scripts as recommended, then the AllSigned execution policy is appropriate. Otherwise, use RemoteSigned. The Unrestricted policy is overly generous and leaves your computer open to a range of attacks, therefore it shouldn't be used.

To check the current execution policy from within PowerShell, run:

 PS:> Get-executionpolicy 

You'll get back information about the current execution policy. If it's Restricted, then you'll know why your scripts won't run.

The execution policy can be changed within PowerShell. Keep in mind that this is changing a value in the system registry to which only administrators may have access. Therefore, if you're not an administrator on your computer, then you may not be able to modify the execution policy. To change the execution policy, run the following within PowerShell:

 PS:> set-executionpolicy RemoteSigned 

This will set the execution policy to RemoteSigned. This change takes effect immediately without restarting PowerShell.

Signing Scripts

Because code-signing certificates can be expensive ($300 per year or more is the current going rate), you may wish to create a self-signed certificate for your own local testing purposes. This certificate will be trusted only by your personal computer, but it costs you nothing to create. To create a self-signed certificate, you'll need a program called Makecert.exe that is available in the downloadable Microsoft .NET Framework Software Development Kit (SDK) at http://msdn.microsoft.com/netframework/downloads/updates/default.aspx. This file is also downloadable form the Windows Platform SDK.;

After downloading and installing this file, you can use the Makecert.exe file to create the certificate by running the following from a Cmd.exe shell:

 C:\> Makecert -n "CN=PowerShell Local Certificate Root" -a sha1  -eku 1.3.6.1.5.5.7.3.3 -r sv root.pvk root.cer  -ss Root -sr localMachine 

Note 

If you have problems running Makecert, run Makecert /? to verify the correct syntax. Different versions of Makecert (a version might be included in your Microsoft Office installation, for example) require slightly different command-line arguments.

Note that this is all one, long line of instructions. Next run:

 C:\> Makecert -pe -n "CN=PowerShell User" -ss MY -a sha1  -eku 1.3.6.1.5.5.7.3.3 -iv root.pvk -ic root.cer 

Again, this is all one, long line of typed instructions. These lines create two temporary files, root.pvk and root.cer, that you can save as backups. The actual certificate will be installed into your local certificate store where it can be used to sign scripts. Within PowerShell, run:

 PS:> Set-authenticodeSignature "filename.PS"  @(get-childitem cert:\CurrentUser\My -codesigning)[0] 

This is also one long line. This line retrieves your code-signing certificate and signs the file named filename.PS, which should be an existing, unsigned PowerShell script. You can run help set-authenticodesignature for additional help with signing scripts. You can also use high-end script development environments such as SAPIEN PrimalScript to sign scripts using a graphical user interface.

We need to emphasize that a certificate made with Makecert is only useful for testing on your local computer. If you want to distribute your scripts internally or externally, you'll need to acquire a real code-signing certificate.



Windows PowerShell. TFM
Internet Forensics
ISBN: 982131445
EAN: 2147483647
Year: 2004
Pages: 289

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net