Skip to content

Instantly share code, notes, and snippets.

@thxCode
Last active December 7, 2023 08:24
Show Gist options
  • Save thxCode/30c8f5efa984627ef4f3bd7df2ebc5a6 to your computer and use it in GitHub Desktop.
Save thxCode/30c8f5efa984627ef4f3bd7df2ebc5a6 to your computer and use it in GitHub Desktop.
Windows Remote POC

Windows Remote

Use PowerShell or PowerShell Core

PowerShell has been a significant component of the Windows operating system for many years now. Although there are no signs that PowerShell is going away, Microsoft has been promoting a PowerShell alternative called PowerShell Core.

Unlike PowerShell, PowerShell Core is multiplatform (Windows, Linux, and macOS).

An important piece of information is that the version of powershell is still up to 5, however, the version number of powershell core starts from 6.

From Powershell Core vs Powershell and googled, there are 2 ways if we want to run powershell inside a container:

  • docker run -it mcr.microsoft.com/windows/servercore:<VERSION> on Windows host, execute powershell after entering the container. This powershell is still Powershell 5.
  • docker run -it mcr.microsoft.com/powershell:<VERSION-PLATFORM> on PLATFORM host, enter the powershell environment directly. This pwsh is Powershell Core.

Therefore, if we want to provide PowerShell operation experience on Linux container platform, we can only choose: mcr.microsoft.com/powershell:<Linux images> or any Linux image that supports PowerShell Core.

Remote Management on PowerShell Core

According to Running Remote Commands, there are 3 ways to support remote computing Windows host via PowerShell Core:

  • WMI (Windows Management Instrumentation)
  • WS-Management (Web Services for Management)
  • SSH

WMI

WMI is the infrastructure for management data and operations on Windows-based operating systems, it is an incredibly powerful feature that allows remote querying and administration of Windows devices.

Connecting to WMI Remotely with PowerShell indicate that we could use Get-WmiObject to connect remote WMI via PowerShell Core.

POC

From my actual test result, Get-WmiObject is still not found in the latest Ubuntu PowerShell Core supported verison(mcr.microsoft.com/powershell:7.0.0-ubuntu-18.04):

WS-Management

WS-Management is a protocol, it provides a standard for constructing XML messages using various web service standards. The messages follow the conventions of Simple Object Access Protocol (SOAP) which is used by all web service protocols.

From WS-Management Protocol, we can know that the WinRM is the Microsoft implementation of WS-Management protocol.

After googled, through Using Credentials to Own Windows Boxes - Part 3 (WMI and WinRM), we further learned that WinRM's backend is utilizing WMI. If WinRM is enabled on the remote machine, it’s trivial to remotely administer the machine from local PowerShell.

Follow Installation and Configuration for Windows Remote Management to setup the WinRM on Windows host, and then use the PowerShell Core container on Linux host to connect.

POC

For quick verification, I used a script to quickly setup the WinRM on Windows host with Basic authentication:

> wget -o ConfigureWinRM.ps1 https://gist.githubusercontent.com/thxCode/cd8ec26795a56eb120b57675f0c067cf/raw/87170b4823eac08d3590a6e7cdf282b7178d4c52/zz_setup_winrm.ps1

# Setup WinRM with basic auth
> .\ConfigureWinRM.ps1 -LogLevel 0 -AuthBasic

Then logged in the same subnet Linux host to test. During the verification process, 2 issues were encountered:

Finally got some help from PowerShell Remoting from Linux to Windows and found an image that can be verified: quickbreach/powershell-ntlm:

> docker run --rm -it --network=host quickbreach/powershell-ntlm

# inside container
PS /> # create a Credential via Windows host administrator account
PS /> $creds = Get-Credential 
PS /> # enter PowerShell session
PS /> Enter-PSSession -Authentication Negotiate -ComputerName 172.31.1.57 -Credential $creds

# dial remote Windows host
PS /> 

Security

Please visit PowerShell Remoting Security Considerations for more security information of WinRM.

SSH

PowerShell remoting normally uses WinRM for connection negotiation and data transport. SSH is now available for Linux and Windows platforms and allows true multiplatform PowerShell remoting.

WinRM provides a robust hosting model for PowerShell remote sessions. SSH-based remoting doesn't currently support remote endpoint configuration and Just Enough Administration (JEA).

Follow PowerShell remoting over SSH to setup the SSH server on Windows host, and then use the PowerShell Core container on Linux host to connect. It is worth noting that all SSH caller need to install the SSH client.

POC

From my actual test result, I could not use New-PSSession in PowerShell Core images (both mcr.microsoft.com/powershell:7.0.0-ubuntu-18.04 and quickbreach/powershell-ntlm) as the SSH client is not installed in these images.

Summary

After POC those 3 ways to connect remotely Windows host via official PowerShell Core image, I got a result as below:

  • Not Supported - WMI - Cannot be used in Linux images that support PowerShell Core.
  • Supported - WS-Management - There is a bug in the official PowerShell Core Linux image, we could use quickbreach/powershell-ntlm instead.
  • Not Supported - SSH - There is not SSH client installed in the official PowerShell Core Linux image.

Addition

In the use of SSH, we can use SSH client Linux image directly:

For quick verification, I used a script to quickly setup the SSH server on Windows host:

> $SSH_USER="frank";
> $SSH_USER_PUBLICKEY="ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDAR2KmePX/.... frank";

# create a remote administrator with public key
> iwr -uri https://gist.githubusercontent.com/thxCode/cd8ec26795a56eb120b57675f0c067cf/raw/897f2c41df99832d6f88f663a9c2ac442dee4875/zz_sshd_manage.ps1 -UseBasicParsing | iex

Then logged in the same subnet Linux host:

# copy frank private key to Linux host: ~/.ssh/frank_rsa

> docker run --rm -it -v /root/.ssh/frank_rsa:/root/.ssh/id_rsa --network=host kroniak/ssh-client ssh -o StrictHostKeyChecking=no frank@172.31.1.57

# dial remote Windows host
PS /> 

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment