Training
Get a free hour of SANS training

Experience SANS training through course previews.

Learn More
Learning Paths
Can't find what you are looking for?

Let us help.

Contact us
Resources
Join the SANS Community

Become a member for instant access to our free resources.

Sign Up
For Organizations
Interested in developing a training plan to fit your organization’s needs?

We're here to help.

Contact Us
Talk with an expert

Month of PowerShell - PowerShell Remoting, Part 1

This may be PowerShell's most immediately-valuable feature for Windows administrators - the ability to run PowerShell commands on remote systems.

Authored byJoshua Wright
Joshua Wright

#monthofpowershell

PowerShell is useful on more than just Windows systems, but it is most powerful on Windows, with full Common Information Model (CIM) support, Windows Management Instrumentation (WMI) access, and full .NET and Component Object Model (COM) APIs. Perhaps the most immediately-valuable feature for Windows administrators is the ability to run PowerShell commands on remote systems.

Since the early versions of PowerShell, Microsoft has added support for cmdlets to run on remote systems with the [code]-ComputerName[/code] parameter:

PS C:\Users\Sec504> Get-Command -ParameterName ComputerName | Where-Object -Property CommandType -Eq Cmdlet | Select-Object -Property Name

Name
----
Add-Computer
Clear-EventLog
Connect-PSSession
Connect-WSMan
Disconnect-WSMan
Enter-PSSession
Get-EventLog
Get-HotFix
Get-Process
...

The [code]-ComputerName[/code] parameter is a .NET capability exposed in PowerShell for easy access:

PS C:\Users\Sec504> Get-Process -ComputerName SEC504STUDENT

Handles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName
-------  ------    -----      -----     ------     --  -- -----------
    260      16     4780       2780       0.48    564   1 ApplicationFrameHost
    241      14     5544      28412      13.77   1468   1 conhost
    227      14     5604      24672       4.36   4324   1 conhost
    102       7     6232       1248              4896   0 conhost
    641      48    25316        924       0.67   7056   1 Cortana
    609      22     1864       2024               416   0 csrss
...

The Microsoft documentation for remote access using [code]-ComputerName[/code] indicates that this remote access capability in select PowerShell cmdlets uses "varying communication protocols". In modern environments where only restricted access to SMB is permitted, you may find that remote access with these commands may not work.

Microsoft has instead indicated that remote access in PowerShell will be built with the WS-Management protocol using HTTPS and the Simple Object Access Protocol (SOAP) protocol using XML data structures.

Microsoft makes remote access to Windows systems with PowerShell broadly accessible with just a few commands:

  • [code]Enable-PSRemoting[/code]/[code]Disable-PSRemoting[/code]
  • [code]Enter-PSSession[/code]/[code]Exit-PSSession[/code]
  • [code]Invoke-Command[/code]
  • [code]New-PSSession[/code]/[code]Remove-PSSession[/code]

In this article we'll look at [code]Enable-PSRemoting[/code] and [code]Enter-PSSession[/code]. We'll follow up with more scalable PowerShell remote access in a second article.

Don't Make Me Come Over There

By default, Windows Server 2012R2 and later have PowerShell remote access turned on by default. Windows 10 and Windows 11 systems have this feature turned off by default. To turn on PowerShell remote access, an administrator can run the [code]Enable-PSRemoting[/code] command:

PS C:\WINDOWS\system32> Enable-PSRemoting
WinRM has been updated to receive requests.
WinRM service type changed successfully.
WinRM service started.

WinRM has been updated for remote management.
WinRM firewall exception enabled.

When you run [code]Enable-PSRemoting[/code], Windows makes several changes to the local Windows configuration:

  1. Starts the WinRM service, listening on TCP port 5985
  2. Changes WinRM to start automatically
  3. Makes Windows firewall changes to permit access to TCP port 5985
  4. Configures the WS-Management remote access feature for PowerShell use

In order to access the remote PowerShell session, you must have Administrator access to the remote system. This could be that your logged in user has Administrator access on the remote system, or that, when the system is part of a domain, you have Domain Admin access. From the Microsoft documentation:

With the appropriate permissions, remote access to PowerShell is straightforward: run [code]Enter-PSSession[/code] and specify the target host name or IP address using [code]-ComputerName[/code]:

PS C:\WINDOWS\system32> Enter-PSSession -ComputerName SEC504STUDENT
[SEC504STUDENT]: PS C:\Users\Sec504\Documents>

Notice how the prompt changes to indicate the remote system name. From here you can run any PowerShell command accessible on the remote system:

PS C:\WINDOWS\system32> Enter-PSSession -ComputerName SEC504STUDENT
[SEC504STUDENT]: PS C:\Users\Sec504\Documents> Get-Service | Where-Object -Property Status -EQ Running

Status   Name               DisplayName
------   ----               -----------
Running  AarSvc_75beb       Agent Activation Runtime_75beb
Running  Appinfo            Application Information
Running  AppXSvc            AppX Deployment Service (AppXSVC)
Running  AudioEndpointBu... Windows Audio Endpoint Builder
Running  Audiosrv           Windows Audio
Running  BFE                Base Filtering Engine
...

When you are done with your PowerShell remote session, run [code]Exit-PSSession[/code] to return to your host system.

[SEC504STUDENT]: PS C:\Users\Sec504\Documents> Exit-PSSession
PS C:\WINDOWS\system32>

If your logged-in user does not have the remote access privileges and you want to use alternate credentials, save the credentials to a variable with [code]Get-Credential[/code]. You will be prompted to enter authentication credentials:

PS C:\WINDOWS\system32> $cred = Get-Credential

cmdlet Get-Credential at command pipeline position 1
Supply values for the following parameters:
Credential
PS C:\WINDOWS\system32> $cred

UserName                     Password
--------                     --------
sec504   System.Security.SecureString

Supply the variable [code]$cred[/code] as an argument to [code]Enter-PSSession[/code] using the [code]-Credential[/code] option:

PS C:\WINDOWS\system32> Enter-PSSession -ComputerName SEC504STUDENT -Credential $cred
[SEC504STUDENT]: PS C:\Users\Sec504\Documents> $env:USERNAME
Sec504
[SEC504STUDENT]: PS C:\Users\Sec504\Documents> Exit-PSSession
PS C:\WINDOWS\system32>

[code]Enter-PSSession[/code] is a useful feature for administrators (and like many things in PowerShell, valuable for attackers as well), but it is only appropriate for interactive 1:1 access to systems. In our next article on PowerShell remoting we'll look at the scalable features of remote access in PowerShell, script blocks, one-to-many sessions, and more. Stay tuned!

-Joshua Wright


Joshua Wright is the author of SANS SEC504: Hacker Tools, Techniques, and Incident Handling, a faculty fellow for the SANS Institute, and a senior technical director at Counter Hack.

Month of PowerShell - PowerShell Remoting, Part 1 | SANS Institute