Discussion: Community Brainstorming: PowerShell Security versus malicious code

This thread is for discussion of the article Community Brainstorming: PowerShell Security versus malicious code. Please share your thoughts!

My answer was, “the right tool for the right job.”

Sometimes I don’t need performance - I’m working with small sets of objects, for example. Sometimes, “who” will maintain the thing dictates the form. Functions aren’t merely a mater of convenience; programming a .NET application (cmdlet) can be significantly more complicated. By the same token, if what I have are .NET devs, then a cmdlet is what I’ll get. As with most things in IT, the answer probably has a lot more to do with organizational and business questions than technical ones, in most cases.

That’s good feedback for the “Cmdlet or Advanced Function?” article. This thread is for a different post, though. :slight_smile:

Matt’s response from the article:

Thanks for posting this, Dave. Ultimately, my stance on the matter is that I believe that a non-admin user should be able to do little to nothing with PowerShell out of the box. I would even go so far as to advocate forcing NoLanguage mode. Of course, just like with the execution policy (which is not a security mitigation), you would easily be able to re-enable functionality for the user using a cmdlet along the lines of Set-LanguageMode. Some have argued against such a mitigation because they claim that it’s game over anyway if you can already execute code on the compromised machine even as a non-admin. While there is some truth to that, at least PowerShell wouldn’t be used as the primary attack vector. An attacker may have to resort to other techniques that are more likely to be detected – e.g. downloading and executing malicious executables. Forcing an attacker to resort to alternate attack technique are much more likely to be detected.

Along those lines, it would also be great if there was more verbose event logging for PowerShell out of the box. I’ve analyzed several malware campaigns where PowerShell was used as the primary attack vector. The existing entries in the event log indicated that PowerShell was used for an attack but it didn’t give any insight into what was performed. It’s possible to gain additional insight into an attack by tapping into the PowerShell ETW provider with the Enable-PSTrace cmdlet but of course, if you’ve already been compromised, this detection technique is useless after the fact.

Of course, my opinion is biased towards the side of security versus usability because I’ve seen how devastating malware infections are on an enterprise. I’d love to hear the merits of those with opposing opinions though.


I think we might not be 100% on the same page, but definitely in the same general area. I don’t think it’s a good idea to force people to be running as Administrator to get to Full Language functionality. This would likely give people incentive to run PowerShell processes as Admin that otherwise wouldn’t have to, increasing their vulnerability rather than decreasing it.

As I mentioned on your blog the other day, I think there are at least a couple of ways to lessen the impact of such a change, while still adding a security layer against malware. One, allow signed, trusted scripts to run by anyone, just as they do today. Two, give normal processes a way to “elevate” PowerShell to Full Language mode interactively, without necessarily being tied to UAC. As long as the elevation (like UAC) requires interaction on the secure desktop, we should be able to get the best of both worlds.

Excellent question Dave.
I don’t have an effective answer, but i have some ideas.

We have an unusual situation with securing Powershell.
We need to execute Powershell scripts for genuine SysAdmin tasks and we need to ban execution of non-approved REPL, byte-Encoded, or any other form of scripts. This doesnt fall into a Application WhiteList, GP, EMET, Anti-Virus,Anti-Rootkit security model we have today.
Also large scale PKI deployments are not easy to manage without dedicated teams.

My suggestion:
a) On production desktops and servers, ban Powershell REPL and Powershell_ISE via Group Policy. ISE doesnt need to be there on Servers OR desktops. (Would you put Visual Studio on a production server ?)
ISE and REPL can be made available in a separate DEV domain for script development, isolated by separate VLAN’s, separate domain.
No constrained endpoints here - just ban.

b) How do I launch powershell scripts on a target machine for genuine SysAd tasks ?
Implement a custom Powershell host, which acts as constrained End-Point by default. Powershell execution is exposed via a service, which responds on a port.
For every Powershell script launched from the Custom Host, it calls a web-service.
The host sends a check-sum + Machine’s GUID to the service.
The web-service, does a check-sum of the script from the signed script in your SourceControl repo and responds OK/Not-OK to the custom host, after authenticating the machine with AD. (If you pawn the source control repo and modify the signed scripts, the checksum fails, and the script fails to execute)
The host logs all before, during and after calls to an external logCollector (Syslog on port 514 UDP).
The host should also provide some cross-cutting tools, like Error Logging, Job-Scheduling, Job-triggers, ETW traces, and other ENV: data + date/time.

How do you launch modules, custom functions you have authored ?
Modules live in a SourceControl \module trunk.
Invoke modules and custom-functions using something like Invoke-CommandAST here.

Other things to consider:
a) What is the Skill-Level of the team.
b) How paranoid are the SysAdmins
c) How high-risk is the environment.

You need to develop a tool for authoring custom-host and the web-service ONCE, and release it.
People can customize, add more layers, two-factor it for interactive session etc. and extend.
I am sure I will have some pull-requests for such a project. :slight_smile:

I know this sounds overtly complicated for a small environment.

Let me know what you think.

Other non-solutions considered:
a) Any user auth / RBAC / delegation based mechanism.
> Doesn’t cut it in a Mimikatz world.
b) Any logging, evented (Action->Response) based options.
> The first event, may defeat your protection mechanisms.
c) Plain constrained end-point without external web-service Auth.
> Someone will figure out a way to by-pass this, sooner or later.
d) Any machine specific security model, without external verification.
> How do you know you are not compromised, if someone else didnt tell you - you are not.

I sincerely think, some real security experts should comment on this. I am closer to a n00b level on security.

Interesting post, if we look at what is currently out there PowerShell is used by public exploits to facilitate tasks during exploitation, most examples are client side attacks against IE or leveraged by malicious Java Applets. We have also started to see it being used inside malicious macros and used in ramsomware so the the threat is real. From a sysadmin perspective solutions should be able to be applied uniformly across a entire network that as real world will be a mixed of different versions of PowerShell and Windows so a solution from MS must allow for this. As Matt mentioned auditing is important, as part of our regular monitoring of the systems for performance, availability and security like we do for most of our environment so better logging to the event log that we can control is important in my opinion. Better control on what cmdlets are allowed to run and under what privilege, same goes for controlling access to .Net. Some of these basic measure will provide control and reduce the chance of entry using existing tools used to manage and monitor a Windows environment.

From the point of view if they are inside they can do what they want when referring attacker I have seen pentesters, malware and hackers suffer because there are local controls in place. It means they have to spend time bypassing them and many times this will increase their forensic footprint and make an attack more prone to be detected. It will also break automated tools that expect a default configuration and block novice attacker whose skill set is still not developed. There is a Murphy law of combat that says “Professionals are predictable but the world is full of amateurs” The same applies to attackers in the cyber realm.

This are just my 0.02 since coffee has not kicked in this morning.

Is there any way to have the node name in configuration data file to be changed through program or and command. Actually I am creating DSC scripts and after that I am provisioning a new VM so till the Vm is created I dont know the node name and my DSC scripts are copied there and then they needs to be run, so I want to change the node name automatically in Configuration data after VM is created.

Thanks in advance :slight_smile: