← Back Published on

Implementing PowerShell Security

Windows PowerShell is a very powerful administrative tool. As a security professional, we will need to control what PowerShell scripts run on our Windows servers. There are individual PowerShell cmdlets, and there are settings configured through Group Policy. Group Policy allows Active Directory administrators to centralize configuration control. 

  • We will create a Group Policy Object (GPO) to manage PowerShell logging. 
  • We will then create a script and explore the available execution policies. 
  • We will digitally sign our script to provide an additional layer of security. 
  • Next, we'll edit the GPO to centrally manage the execution policy. To match the 515support company security policy, we will disable PS remoting. 
  • Finally, we will review the PowerShell log files that you enabled at the start of the activity.

Configure a GPO for PS Logging

Configure a Group Policy Object that enables logging and link it to the corp.515support.com domain.

From the Server Manager, we navigate to Group Policy Management and right-click the  corp.515support.com domain object and select Create GPO in this domain, and Link it here.

We name the GPO "PowerShell Security GPO"

We right-click and select edit on the PowerShell Security GPO. In the GPO editor, we select Computer Configuration > Policies > Administrative Templates > Windows Components > Windows PowerShell and we right-click the Turn on PowerShell Script Block Logging and select edit and then enable it.

Next, we return to the Group Policy Management window, select the Group Policy Objects folder. We then right-click the PowerShell Security GPO and save it to the desktop with the default file name. 

Next, we open Windows PowerShell as an admin and run gpupdate /force twice.

Manage PowerShell Execution Control

We will configure PowerShell execution control on the DC1 virtual machine. We would not be likely to create and test scripts on a domain controller. We are just using this VM to simplify the lab environment requirements.

PowerShell execution policy reference table:

Setting:Description
UnrestrictedNo requirements; all scripts allowed
RemoteSignedLocal scripts allowed; remote scripts must be signed
AllSignedLocal and remote scripts must be signed
RestrictedNo scripts allowed

Next, we'll return to server manager and open Windows PowerShell ISE and add the following script to the Untitled.ps1 script pane and execute the code.

The script runs and displays the script contents and the formatted script data.

We'll save this script to the desktop as PSversion.ps1 for now.

Now that it's saved on the desktop, we'll navigate to the desktop in windows powershell and execute the script from here. We can see that the PowerShell version installed on this machine is 5.1 under Major and Minor.

Let's find out what the current execution control policy on the system is.

Next, let's review the following snippet of the organization's written security policy as it pertains to scripts and security:

  • Scripts created in-house must be digitally signed. Such scripts may be signed with a self-signed certificate. Scripts downloaded from the Internet must be digitally signed by a trusted source. The PowerShell execution policy will be set as AllSigned.

We'll configure the PowerShell Execution Policy to match the requirements by running the following code: Set-ExecutionPolicy -ExecutionPolicy AllSigned -Scope LocalMachine

This type of configuration usually enforced through Group Policy. When we try to run our PSversion.ps1 script again it fails because it is not digitally signed. 

Let's verify both what the execution policy is set to, and what the status is of the PSversion.ps1 script is.

Create a Code Signing Certificate

According to the company policy, you need to digitally signed our PowerShell scripts. We will generate a code signing certificate and link it to the test script.

In the PowerShell window, we'll run the following cmdlet to generate a new self-signed certificate:  New-SelfSignedCertificate -DnsName administrator@corp.515support.com -CertStoreLocation Cert:\CurrentUser\My\ -Type Codesigning

Next, we'll open the certificates MMC by running the certmgr.msc command. We'll expand the Personal node and Select the Certificates node. Here we can see two certificates displayed. Including our newly created Code Signing certificate.

We'll double-click the new Code Signing Certificate, navigate to the details tab, and select Copy to File. We'll complete the wizard by making the following sections:

  • Select No, do not export the private key
  • Select DER encode binary X.509 (.CER) format
  • Browse to the Desktop and save the file with the name code-cert

Now, when we navigate to the desktop, we can see the certificate icon.

In the certmgr console, we'll right-click Trusted Root Certification Authorities, and then select All Tasks > Import.

In the Certificate Import Wizard, specify the code-cert.cer file from the Desktop, accept all other defaults, and then select Finish. We'll select yes and then ok when prompted to install the certificate.

From the PowerShell console, run the following cmdlet to digitally sign the PSversion.ps1 script: Set-AuthenticodeSignature -FilePath C:\Users\Administrator\Desktop\PSversion.ps1 -Certificate (Get-ChildItem -Path Cert:\CurrentUser\My\ -CodeSigningCert)

Now when we run the PSversion.ps1 script again it'll execute successfully because the script is now digitally signed.

Let's quickly confirm the status of the script.

Configure a GPO that Enforces the Execution Policy

An advantage of using Group Policy to configure the execution policy, rather than a standard PowerShell cmdlet, is that Group Policy provides cetralized configuration of many machines, and is easily edited.

We will edit an existing Group Policy Object (GPO) to set the execution policy as AllSigned, and link it to the corp.515support.com domain.

In the Group Policy Management console, we'll expand the corp.515support.com domain object, right-click the PowerShell Security GPO GPO, and then select Edit.

In the GPO editor, select Computer Configuration > Policies > Administrative Templates > Windows Components > Windows PowerShell.

Here we'll enable Turn on script execution and select Allow only signed scripts under the execution policy.

    Disable Remote PowerShell

    The 515 Support security policy states that PowerShell cmdlets must only be run locally on Domain Controllers. We must disable PowerShell Remoting on DC1 to prevent users from establishing remote PowerShell sessions. Such sessions would permit the remote execute of cmdlets such as Restart-Computer or Get-Service on the DC.

    Review the following snippet of the organization's written security policy as it pertains to scripts and security:

    • The Remote PowerShell functionality will be disabled on all Domain Controllers.

    We'll run the following commands to disable Powershell Remoting and verify it's status is AccessDenied.

    After browsing the displayed entries, we can see text indicating that the PSversion.ps1 script could not be run because it is unsigned.

    Attempting to run an unsigned script was an earlier task in the activity, and is an example of a suspicious entry. Such entries indicate someone may be trying to run unauthorized scripts in your environment.

    Review PowerShell Logging

    Through this lab, we were able to control what PowerShell scripts run on our servers and create a Group Policy Object (GPO) to manage PowerShell logging. We also explored the available execution policies, digitally signed our script to provide an additional layer of security, and edited the GPO to centrally manage the execution policy. Furthermore, we disabled PS remoting to match the 515support company security policy and reviewed the PowerShell log files that we enabled at the beginning of the activity.

    Log files are a critical component of server security. You will display and filter PowerShell log files for suspicious events.

    In Server Manager's Event Viewer, we'll navigate to Applications and Services > Microsoft > Windows > Powershell, and then select the Operational log.

    In the actions pane on the right, we select Filter Current Log and replace All Event ID's with 4100 and select ok.

    Conclusion