Главная

Wednesday, 20 October 2021

PowerShell Security book #1.

Hi all.

Today I would like to present for your eyes the best e-book of authors Michael Pietroforte and Wolfgang Sommergut "PowerShell Security".

These authors describe in details security features in Powershell:

  • Control execution of scripts using execution policy, code signing and constrained language mode
  • Secure PowerShell remoting with SSH und TLS
  • Delegate administrative tasks with JEA
  • Audit and analyze PowerShell activities, encrypt logs
  • Improve code quality following best practices.

PowerShell is a powerful tool for system administration and as such also a perfect means for hackers. Due to the tight integration into the system, attempts to simply block PowerShell provide a false impression of security. The best protection is provided by PowerShell's own mechanisms. PowerShell offers almost unlimited access to the resources of a Windows computer and also can automate numerous applications such as Exchange. Users aren't limited to the many modules and cmdlets, but can also integrate .NET classes, Windows APIs, and COM objects. These capabilities are particularly dangerous in the hands of attackers. Since many versions of With Windows Server, Microsoft avoids to activate any roles and features on a freshly installed machine in order to minimize the attack surface. On such a locked down system users must explicitly add all required services.



So, now I try to explain for you these features in practically. Let's go.

# Execution scripts.

We can define policies for execution Powershell scripts on the host by:

  • GPO
  • signing our script
  • set constrained language mode.

# Execution policy.

I prefer set RemoteSigned mode. It means that Scripts downloaded from the Internet must be signed by a trusted publisher.

How it set?

  • Set-ExecutionPolicy RemoteSigned
  • Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
  • $env:PSExecutionPolicyPreference

How it check?

Get-ExecutionPolicy -List | ft -AutoSize

We can set Turn on Poweshell script execution by GPO.

How it set?

mmc: Policies => Administrative Templates => Windows Components => Windows PowerShell and is called Turn on Script Execution.

Result: powershell.exe -ExecutionPolicy "Unrestricted" doesn't work!

However you can bypass it as following:

a) If a user decides to circumvent this policy, he simply copies the contents of a script to the ISE and runs it there. 

b) RemoteSigned allows unsigned scripts downloaded from the Internet to be started if you unblock the file using Unblock-File.

c) Another bypass consists of encoding the script in Base64 and transferring it to PowerShell.exe via the EncodedCommand parameter. 

To limit possible damage caused by such activities, it is recommended to use the Constrained Language Mode.

# Signing code.

You can use your corporative CA-server for issuing certificate:

https://CA-server-name/certsrv

Choose template: "Code Signing" and so on.

-OR-

Create template for Certificate...

Create Certificate...

Personal => All Tasks => Request New Certificate.

Enroll ...

And don't forget to move new Certificate from container Intermediate to Trusted Root.

Ok, check your Certificates:

Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert

Check and set your Execution Policy as AllSigned:

Get-ExecutionPolicy

Set-ExecutionPolicy AllSigned –Force

Get-ChildItem Cert:\CurrentUser\My –CodeSigningCert

$cert = (Get-ChildItem Cert:\CurrentUser\My –CodeSigningCert)[0]

Move-Item -Path $cert.PSPath -Destination "Cert:\LocalMachine\Root"

Set-AuthenticodeSignature myScript.ps1 -Certificate $cert


The Set-AuthenticodeSignature cmdlet has a special TimestampServer parameter that specifies the URL for the Timestamp of the service. If this parameter is left blank, then the PS script will stop running after the certificate expires. 

For example: -TimestampServer http://timestamp.verisign.com/scripts/timstamp.dll

-OR-

Set-AuthenticodeSignature myScript.ps1 -Certificate $cert -TimestampServer http://timestamp.glob-alsign.com/scripts/timstamp.dll -HashAlgorithm "SHA256"

Get-AuthenticodeSignature MyTest.ps1 | ft -AutoSize

The root CA certificate and the certificate signed by the script must be trusted (otherwise the script will not run at all). You can centrally install certificates to all computers in the domain using GPO. The certificates should be placed in the following GPO sections:

Computer Configuration -> Policies -> Windows Settings -> Security Settings -> Public Key Policies -> Trusted Root Certification Authorities и Trusted Publishers.

# Constrained Language Mode.

You can set LanguageMode easy:

$ExecutionContext.SessionState.LanguageMode = "ConstrainedLanguage"

1) If System environment variable __PSLockDownPolicy set it to 4, so Powershell run in restricted mode ONLY.

A disadvantage of this procedure is that it always affects all users of a host, including administrators! However, administrators may temporarily remove the environment variable until the GPO becomes effective again. But this is quite cumbersome and definitely not a good solution.

2) Automatic detection of an execution constraint - creates a module and a script (with a name following the pattern __PSSCRIPT-POLICYTEST_LQU1DAME.3DD.PSM1) under $env:temp and tries to execute them. If AppLocker or another tool blocks this attempt, PowerShell will start in restricted language mode. So you have to reconfigure AppLocker OR activating Constrained language mode via SRP.

3) You will need to remove PowerShell 2.0 Engine.

Check it: Get-WindowsOptionalFeature -Online -FeatureName MicrosoftWindowsPowerShellV2

However if you need v2.0 you can start PS as: powershell.exe -version 2.0

# Communication with hosts by:

  • SSH
  • Certificate
  • HTTPS.

# SSH.

Get-WindowsCapability -Online | ? name -like *OpenSSH.Server*

-OR-

Get-WindowsCapability -Online | where name -like *OpenSSH.Server* | Add-WindowsCapability -Online

Set-Service sshd -StartupType Automatic

Set-Service ssh-agent -StartupType Automatic

To put the SSH server into operation immediately, you must also start the two services manually:

Start-Service sshd

Start-Service ssh-agent

Check SSH services: Get-Service -Name *ssh* | select DisplayName, Status, StartType

Check SSH firewall rules: Get-NetFirewallRule -Name *SSH*

Check SSH connections: ssh <Name of SSH Server>

1) Local configuration.

ssh-keygen - by default, the command saves the key pair in the .ssh folder in your user profile. id_rsa is the private key, and id_rsa.pub is the public key.

Start-Service ssh-agent

If you want the service to start automatically after a restart, you can use this command:

Set-Service ssh-agent -StartupType Automatic

To add(remove) your private key to the ssh-agent, you have to enter this command:

ssh-add <path to private key>

ssh-add .ssh\id_rsa

ssh-add -d .ssh\id_rsa

2) Remote configuration.

Copy the contents of the public key file id_rsa.pub to the remote host to the authorized_keys file in C:\Users\<your user name\.ssh\

Disabling password authentication in sshd_config file set:

PasswordAuthentication no

Restart-Service sshd

3) Connection with key.

Enter-PSession -HostName <remote host> -UserName <user name on the remote computer>

Invoke-Command -HostName <remote hosts> -UserName <user name on the remote computer> -ScriptBlock {get-process}

-OR-

ssh <user name on the remote computer>@<remote host>

ssh -i <path to private key>id_rsa <user name on the remote host>@<remote host>

Enter-PSsession and Invoke-Command have the -IdentityFilePath parameter for this purpose:

Enter-PSession -HostName <remote host> -UserName <user name on the remote host> -IdentityFilePath <path to private key>id_rsa

# Self-signed sertificate.

1) Creating a certificate with default values:

New-SelfSignedCertificate -DnsName lab.contoso.de -CertStoreLocation Cert:\LocalMachine\My

dir Cert:\LocalMachine\my\<thumbprint-of-certificate> | fl -Property *

For creating wildcard certificates:

New-SelfSignedCertificate -DnsName lab.contoso.de, *.contoso.de -cert Cert:\LocalMachine\My

This example sets the validity to 2 years:

New-SelfSignedCertificate -DnsName lab.contoso.de -CertStoreLocation Cert:\LocalMachine\My -NotAfter (Get-Date).AddYears(2)

In addition to the default value SSLServerAuthentication, the Type parameter also accepts these values:

- CodeSigningCert

- DocumentEncryptionCert

- DocumentEncryptionCertLegacyCsp.

2) Export certificate:

$CertPW = ConvertTo-SecureString -String "secret" -Force -AsPlainText

 It is then passed to the parameter Password when calling Export-PfxCer-tificate:

Export-PfxCertificate -Password $CertPW ` -Cert cert:\LocalMachine\My\<Thumbprint> myCert.pfx

# HTTPS.

For communication between hosts via HTTPS you need WinRM service.

You have to check it:

winrm get winrm/config

dir WSMan:\localhost\Service | ? Name -eq AllowUnencrypted

dir WSMan:\localhost\Client | ? Name -eq AllowUnencrypted

1) So you have to enable HTTPS on the remote computer:

Set-WSManQuickConfig -UseSSL

$Cert = New-SelfSignedCertificate -DnsName "myHost" -CertstoreLocation Cert:\LocalMachine\My

Export-Certificate -Cert $Cert -FilePath C:\temp\cert

Enable-PSRemoting -SkipNetworkProfileCheck -Force

dir wsman:\localhost\listener

Remove the HTTP listener this way:

Get-ChildItem WSMan:\Localhost\listener | Where -Property Keys -eq "Transport=HTTP" | Remove-Item -Recurse

Removes all WSMan listeners:

Remove-Item -Path WSMan:\Localhost\listener\listener* -Recurse

Add our WSMan HTTPS listener:

New-Item -Path WSMan:\LocalHost\Listener -Transport HTTPS -Address * -CertificateThumbPrint $Cert.Thumbprint -Force

New-NetFirewallRule -LocalPort 5986 -Protocol TCP -DisplayName "Windows Remote Management (HTTPS-In)" -Name "Windows Remote Management (HTTPS-In)" -Profile Any

Set-Item WSMan:\localhost\Service\EnableCompatibility-HttpsListener -Value true

Set-NetConnectionProfile -NetworkCategory Private

Disable the firewall rule for HTTP that Enable-PSRemoting added:

Disable-NetFirewallRule -DisplayName "Windows Remote Man-agement (HTTP-In)"

2) And, of course, you have to enable HTTPS on the local computer:

Import-Certificate -Filepath "C:\temp\cert" -CertStoreLocation "Cert:\LocalMachine\Root"

Enter-PSSession -ComputerName myHost -UseSSL -Credential (Get-Credential) 

-OR-

Enter-PSSession -ComputerName myHost -UseSSL -Credential (Get-Credential) -SkipCACheck

Ok, this story be continued.

No comments:

Post a Comment

А что вы думаете по этому поводу?