Say what’s up to PowerShell 5 (Part 23/27)

Here’s PowerShell remoting summed up in one word: addictive.

Once you see how powerful this thing is you’ll never go back to opening remote desktop to RDP into a box again…

Traditionally, if you have a bunch of servers you need manage you might open up a Remote Desktop session into each one, do your business and leave.  Or perhaps you have a remote desktop connection manager program that manages all your connections for you.

That was me.  I was in your situation before I met PowerShell 🙂

One command, hit all the machines and smile.

What is PowerShell remoting?

PowerShell Remoting is a way to execute PowerShell commands on remote compuers.  You end up sending the commands (basically XML data) over HTTP or HTTPS using the WinRM service.  So it doesn’t use DCOM or RPC.  This is great because those protocols are becoming obsolete and aren’t nearly as firewall friendly as HTTP!

A friend of mine once told me a joke.  Do you want to hear a funny Firewall joke?  I said yes and he went: Do you know what HTTP stands for?  And before I could translate he said UFBP: The universal firewall bypass protocol.

That’s because HTTP usually isn’t blocked and means PowerShell remoting is a happy customer across your network infrastructure (for you and the bad guys).  Think of PowerShell remoting like SSH for Windows.

Here are the big ones you need to know:

  • Enable-PSRemoting
  • Enter-PSSession
  • Invoke-Command
  • New-PSSession
  • Connect-PSSession

First let’s see if PSRemoting is enabled on our Windows Server 2016 machines and our Windows 10 hosts.

Type Get-PSSessionConfiguration.  If it’s enabled you should see four endpoints that are waiting to accept your incoming remote connections.

As you can see it’s enabled by default on all Windows Server 2016 boxes.  The same applies for Windows Server 2012 R2.


Conversely, you can see it isn’t enabled by default in Windows 10 but we get the option to enable it.


You can type Y for yes or you can use Enable-PSRemoting to enable Remoting.

The only thing to keep in mind here is if your network profile is set to Public it won’t work (which makes sense because you don’t want people on the internet remoting into your box)

Enable-PSRemoting on Public profile


In this case you can, with caution, skip this check and enable it anyway (which I don’t recommend, instead get on a private network)

Enable-PSRemoting -SkipNetworkProfileCheck

Skip network profile check

Now let’s login to dc16alx1, our Windows Server 2016 Active Directory Domain Controller… (this blows RDP out of the water)

Enter-PSSession dc16alx1


We know we’re on dc17alx1 because the prompt now starts with [dc16alx1]:


Anything we type here is typed as if we were logged in locally to the box.  This is our interactive session that is pretty much like a SSH session for Windows.

when you’re done with your stuff just type Exit-PSSession and you’re out.

Logging into more that one box

Invoke-Command is the cmdlet we use to control multiple servers at once.  This is a big time favorite for PowerShell administrators because it gives them massive control over hundreds or even thousands of computers.

So let’s say we want to see which computers have IIS installed on them.  We don’t want to log into each server manually or pop open RDP.  We want to do it all from the PowerShell command line.

We can use Invoke-Command with a -ScriptBlock parameter which contains the command we want to send to our computers. Then we just specify the computers using the –ComputerName parameter and sit back and smile.

Invoke-Command -ScriptBlock { Get-WindowsFeature web-server } -ComputerName dc16alx1, fs17alx1


You can also create and run scripts across all your computers in an instant.  For example, instead of using the -Scriptblock parameter you could use -FilePath and point it to a script sitting on a file share or on a mapped drive.  When you hit enter it’ll run it on all the computers after the -ComputerName parameter.

Maintaining Persistance

The only issue with Invoke-Command is that it doesn’t persist by default.  So when you run it, it just starts a new PowerShell session on each of the remote machines, runs the ScriptBlock or script inside your -FilePath and then tears down the session.  In other words, it doesn’t persist!

So let’s create a new session and store it in a variable so it can persist.

$dc = New-PSSession dc16alx1

Then we can take a look at the session with Get-PSSession


and connect to it:

Enter-PSSession $dc

Then if we do some work in the session, and close down the PowerShell prompt we can pickup where we left off by simply getting the PSSession back with Get-PSSession and  retrieving our work with Invoke-Command and the -Session parameter

$dc2 = Get-PSSession -ComputerName dc17alx1 | Connect-PSSession

Now w’ere connected to the session and we can interact with it just as if we never left.  Think of it like disconnecting from an RDP session without logging off; you just clicked the X button.

Powershell Security

All this talk about running scripts and using remoting might have you wondering about security.  Exactly how secure is PowerShell?

So scripts run in the security context of the logged in user.  If you’re logged in as an Administrator and attempt to run a script it will run with elevated privileges.  Similarly, if you’re logged in with non-admin privileges it reduces the possibility of damage.

Another thing is that by default, Scripts don’t just execute or run by double-clicking them.  If I send you a malicious PowerShell script as an email attachment and you double click it it’ll just open Notepad; it won’t actually run.

Execution policies

Perhaps the most important concept to understand in PowerShell security are Execution Policies.

Restricted is the default policy. This means, by default you can only run individual commands but not scripts.  The opposite of this is Unrestricted which means “anything goes”.

Technically, that’s not true.  Bypass is the ultimate security risk because not only is nothing blocked there are no warnings or prompts.  So why would you use it?  It was designed for developers who need to test system configurations.

Unfortunately the bad guys also use this during post-exploitation.  After exploiting a weakness in your system and gaining a foothold, they will usually set the execution policy to ByPass.

I usually like to keep my execution policy set to RemoteSigned because that means any downloaded scripts need to a digital signature from a trusted publisher before PowerShell will run it.  All local signed and unsigned scripts will run but if it was downloaded from the web it needs a valid sig.

To see your current execution policy type:



and to change it to RemoteSigned you can use Set-ExecutionPolicy.

Set-ExecutionPolicy RemoteSigned




Connect with Vonnie on Twitter

Posted in Windows, Windows 10 Tagged with: