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, executepowershell
after entering the container. Thispowershell
is still Powershell 5.docker run -it mcr.microsoft.com/powershell:<VERSION-PLATFORM>
on PLATFORM host, enter the powershell environment directly. Thispwsh
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.
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 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.
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 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.
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:
- PowerShell will no longer support Basic Auth over HTTP specifically due to unencrypted credentials and payload: PowerShell/psl-omi-provider#114 (comment), we could use Negotiate Auth instead: PowerShell/PowerShell#6647 (comment)
- Official PowerShell image (
mcr.microsoft.com/powershell:7.0.0-ubuntu-18.04
) doesn't support NTLM until PowerShell/PowerShell-Docker#124 closed
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 />
Please visit PowerShell Remoting Security Considerations for more security information of WinRM.
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.
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.
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.
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 [email protected]
# dial remote Windows host
PS />