A Story About Blocking PowerShell

A Story About Blocking PowerShell

Michael Schneider
by Michael Schneider
time to read: 8 minutes

Perl is considered to be the Swiss Army Knife among programming languages. This title could soon be passed on to PowerShell (PS). PowerShell is a command line and scripting language that focuses on system administration. It is based on the .NET framework, integrated deep into the operating system and it has a massive amount of functions. In brief: Should an attacker gain access to PowerShell, he will have a very powerful tool at his disposal. It will greatly raise the number of things he’s able to do and he can bypass many a limitation. Following a security audit, I am often asked how I can control the execution of PowerShell or how it could be blocked. In this Labs, I will try to answer those questions.

The Goal

When doing Red Team jobs, I pretend to be an attacker. As such, I know tricks that allow me to circumvent restrictions and that allow me to execute commands and access information that I shouldn’t be able to access. However, I need to switch my point of view to that of a Blue Team, who defend rather than attack. Taking the role of a system administrator, I want to secure the system in a way that undesired programs can’t be executed. In case of PowerShell, more factors than just a simple deactivation of the program come into play.

Because PowerShell is very useful for the work of a system administrator and most likely, it is in use in the IT infrastructure of the system we are administrating. So if we block PowerShell, one or more programs that use PowerShell are not going to function anymore. Therefore, it’s necessary to break down the initial questions further:

This is where this Labs could end, because PowerShell knows execution policies. I have elaborated on those in my article on The Basics of PowerShell and discovered that they’re not an effective means of protection. Therefore, I have to find an alternate way to limit applications.

I aim to do all this by using the functions that are already integrated into the operating system. Thus, I’ve decided to use Microsoft AppLocker.

Implementation

My Windows test environment is simple: Two virtual machines. One is a Windows Server 2008 R2 acting as domain controller. The other is a Windows 7 Professional VM as a client. That’s where the first problem appears: AppLocker and licenses. Windows 7 Professional can only be used to define AppLocker rules. But they will only be used on licensing levels Enterprise/Ultimate. So my client VM can’t be used for testing. Under Windows 8, Microsoft has revised their licensing policies and can according to the AppLocker FAQ support every Windows 8 version. So I expand my test environment and include a Windows 8.1 client VM.

To distribute the AppLocker rules, I use a group policy. It is defined at Computer Configuration -> Policies -> Windows Settings -> Security Settings -> Application Control Policies -> AppLocker. For a first try I let the program generate standard rules and put a Deny rule on the PowerShell directory, located at %SYSTEM32%\Windows\PowerShell\*.

The PowerShell Deny Rule

By specifying the path to the directory, I deactivate not only powershell.exe but also powershell_ise.exe, which is the PowerShell editor. During my first attempt at testing I have assigned this policy to all users and groups of the domain. It should have been impossible to execute PowerShell. The rule holds true to that assumption. I can’t use neither PowerShell nor PS-scripts on the Windows client. The question of blocking PowerShell is answered.

As mentioned, I have assigned the GPO to the group Everyone. I can change this assigning in a way that the AppLocker policies only apply to certain users/groups. In these cases, I follow the approach of Less is More. This means that when I have less exceptions to a rule, the more beneficial to security it is. Because the policies can be distributed within group policies, it’s possible to define different policies and to assigne them to target objects according to ratings. I can define a very restrictive AppLocker rulebase and assign it to systems that are being limited as much as possible (example: terminal servers). In other systems I can deploy a rulebase that has defined exceptions. This answers the question if certain groups can use PowerShell while others can’t.

On to the last question. What happens if one or more PS-scripts are to be triggered whena user logs in, but the use of PowerShell has been disabled for the user? Because login scripts are executed under the account of the user, AppLocker blocks the PowerShell scripts. In order to be able to continue to use the scripts, there’s an exception in the rulebase needed. Basically, AppLocker can define three categories of rules:

  1. Executables Rules
  2. Windows Installer Rules
  3. Script Rules

Thus far, I have established a Deny rule that covers the PowerShell directory. This is an Executable Rule. Now, I’ll define an additional exception rule for a login script. This falls under Script Rules. Rule of thumb is that a Deny rule will be prioritized. Following this rule, it’s no use or script execution if I have established a Deny rule that supersedes the exception rule because I still can’t execute scripts. In addition to that, I can’t define an exception in an Executables Rule.

Summary here is that when a user’s permissions to run scripts is taken away, there’s no way to run individual scripts. The answer to the question whether or not we can run individual scripts in spite of the Deny rule is No. If we are intent to use PS-scripts with a Deny rule, we have to find another way. If someone knows such a way or has any ideas, I’d be happy to hear them.

During my research, I have discovered an interesting tool named PS2EXE. The tool encapsulates PowerShell code within a PowerShell host object written in C# and generates an EXE file from it. This EXE contains all functions necessary to run PowerShell through a .NET object. However, it can’t be run without an installed version of PowerShell and the .NET framework. However, this EXE doesn’t access powershell.exe and can therefore be executed despite the Deny rule. It’s possible to create one such EXE for every PS script and define it as an exception in an Executable Rule. In addition to that, PS2EXE can be used to circumvent a PowerShell block.

Mind the Surroundings

This is where the story of blocking PowerShell finds its end. It’s possible to block PowerShell with tools Windows has on board. This comes at a price. Some functions, such as PS logon scripts, are suddenly unavailable. It’s not enough to just deactivate PowerShell but the surrounding system needs to be limited as well. Users should not be permitted to execute random programs, but only those that are explicitly allowed or that come from a trusted source. The default rules in AppLockers consider the directories C:\Program Files (%PROGRAMFILES%) and C:\Windows (%WINDIR%) to be trusted. Additionally, users must not have write permissions in any trusted directory so that they can’t put any files there.

About the Author

Michael Schneider

Michael Schneider has been in IT since 2000. Since 2010 he is focused on information security. He is an expert at penetration testing, hardening and the detection of vulnerabilities in operating systems. He is well-known for a variety of tools written in PowerShell to find, exploit, and mitigate weaknesses. (ORCID 0000-0003-0772-9761)

Links

Your Blue Team may use some support?

Our experts will get in contact with you!

×
Reporting and Documenting

Reporting and Documenting

Michael Schneider

Introduction of CVSS v4.0

Introduction of CVSS v4.0

Michael Schneider

Rogue Device

Rogue Device

Michael Schneider

Windows LAPS

Windows LAPS

Michael Schneider

You want more?

Further articles available here

You need support in such a project?

Our experts will get in contact with you!

You want more?

Further articles available here