PowerShell Remoting from Linux to Windows

Disclaimer - All of the information presented is accurate to the best of my knowledge, I am a n00b though.

TL;DR - You can PS-Remote from Linux to Windows if you 1) permit NTLM authentication on a target during post-exploitation, 2) restart WinRM services, and 3) use this NTLM supporting PowerShell Docker image to PS-Remote from Linux to Windows.

Background Info

Occasionally I have found it useful on my pentests to leverage PowerShell remoting as my primary means of maintaining remote code execution on a system. It's a built-in Windows feature that is incredibly useful when living-off-the-land is a requirement due to client detection capabilities. Unfortunately, remoting from my Kali Linux box to my targets has not been an easy task due to authentication mechanisms supported by the Linux branch of PowerShell Core.

PowerShell remoting requires Kerberos mutual authentication, which means that the client machine and target machine must both be connected to the domain. That can pose an issue for us testers if we don't already have a compromised domain-connected box to perform the remoting from. Fortunately, we have the option to add ourselves as a "TrustedHost" in the target's configuration which will permit us to perform NTLM authentication rather than Kerberos and thus removes the need to connect from a system on the domain.

Now the only catch is that PowerShell core for Linux (PowerShell 6.1.0 at the time of writing) does not come with support for NTLM authentication. This isn't the end of the world, as we could always perform PowerShell remoting from a Windows VM. Luckily some Redditors found a way to get NTLM authentication working with PowerShell on Centos, and thus I incorporated their findings into a simple PowerShell Docker image quickbreach/powershell-ntlm.

How to use PowerShell Remoting from Linux to Windows

This section will go through step-by-step how to establish a remote PowerShell session from a Linux client to a Windows target. It is assumed that you have administrative access over your target PC (RDP, payload, etc.).

  1. Enable PowerShell remoting on the target

    Enable-PSRemoting –Force
    
  2. Get a list of the current TrustedHosts on the target system for reference

    Get-Item WSMan:\localhost\Client\TrustedHosts
    
  3. Add yourself as a TrustedHost on the target. This is required in order to use NTLM authentication during the Enter-PSSession setup phase, which is the only authentication mechanism that can be used to connect from Linux to Windows via PowerShell remoting. To accomplish this, run one of the below commands:

    Use a wildcard to permit all machines to use NTLM when authenticating to this host

    Set-Item WSMan:\localhost\Client\TrustedHosts -Force -Value *
    

    Or be specific and add only your IP to the NTLM authentication permitted list

    Set-Item WSMan:\localhost\Client\TrustedHosts -Force -Concatenate -Value 192.168.10.100
    

    TrustedHostExample

  4. Setup and restart the WinRM service to reflect the changes made

    Set-Service WinRM -StartMode Automatic
    
    Restart-Service -Force WinRM
    
  5. Drop into an instance of the PowerShell-NTLM Docker image. The below sample command also mounts a local directory containing PowerShell scripts on the /mnt path inside of the docker image

    docker run -it -v /pathTo/PowerShellModules:/mnt quickbreach/powershell-ntlm
    
  6. And now the moment we've been waiting for: Enter into a remote PowerShell session with the below commands - note that you MUST specify the -Authentication type:

    # Grab the creds we will be logging in with
    $creds = Get-Credential
    
    # Launch the session 
    # Important: you MUST state the  authentication type as Negotiate
    Enter-PSSession -ComputerName (Target-IP) -Authentication Negotiate -Credential $creds
    
    # i.e.
    
    Enter-PSSession -ComputerName 10.20.30.190 -Authentication Negotiate -Credential $creds
    

    You can also use the Invoke-Command function in a similar fashion

    Invoke-Command -ComputerName 10.20.30.190 -Authentication Negotiate -Credential $creds -ScriptBlock {Get-HotFix}
    

    demo

Clean-up

If there were existing TrustedHosts previous to your command to add yourself, swap out your IP and run the below:

$newvalue = ((Get-ChildItem WSMan:\localhost\Client\TrustedHosts).Value).Replace(",192.168.10.100","")
Set-Item WSMan:\localhost\Client\TrustedHosts -Force -Value $newvalue

Or, you can remove all of the TrustedHosts if you were the only one

Clear-Item WSMan:\localhost\Client\TrustedHosts

Restart the WinRM service to complete your changes (Note that this will disconnect you from Enter-PSSession)

Restart-Service WinRM

References:

This Reddit Thread
PowerShell Remoting Cheatsheet

comments powered by Disqus