Powershell Remote Management From Linux

[linkstandalone]

When you are an avid linux fan/user in a windows environment, you try to find ways to avoid having to use a windows computer. As I was exploring different methods of remote administration for windows, I decided to learn about Powershell Remoting. I wanted to try and use the Powershell that is now available for linux, Powershell Core. With earlier versions, I was unable to do much, however, newer versions bring much more useful functionality. In this post, I will talk about how to get set up to remotely administer windows systems from Linux using Powershell Core.

The first step is to install the proper version of Powershell. In order for this to work, you need to have a newer version of Powershell installed. As of writing this post, the current version on which this works is 6.2.3. The reason for this is that its a relatively new feature for linux powershell.

Installation

CentOS/RHEL
Add the Microsoft repo
    curl https://packages.microsoft.com/config/rhel/7/prod.repo | sudo tee /etc/yum.repos.d/microsoft.repo

Install the package
    sudo yum install powershell

By default we do not have NTLM authentication so install this package
    yum install -y gssntlmssp
Arch Linux using yay AUR Helper
Install the package
    yay -S powershell-bin

By default we do not have NTLM authentication so install this package
    yay -S gss-ntlmssp
Ubuntu
Download the deb from Microsoft according to your linux version
  wget https://packages.microsoft.com/config/ubuntu//packages-microsoft-prod.deb

Install the package to register the Microsoft repo GPG keys
  dpkg -i packages-microsoft-prod.deb

Update your repo database
  sudo apt update

Install the package
  sudo apt install powershell

By default we do not have NTLM authentication so install this package
  sudo apt install gss-ntlmssp
Debian 9
Install some pre-reqs if you do not have them already
    sudo apt-get install -y curl gnupg apt-transport-https

Import the Microsoft repo GPG keys
    curl https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add -

Add the Microsoft repo
    sudo sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-debian-stretch-prod stretch main" > /etc/apt/sources.list.d/microsoft.list'

Update your repo database
  sudo apt update

Install the package
  sudo apt install powershell

By default we do not have NTLM authentication so install this package
  sudo apt install gss-ntlmssp
For any other distro please refer to Microsoft's Documentation

Setting up the client with physical access to the system

  1. Check if PS Remoting is enabled
  2.      Get-PSSessionConfiguration
         
  3. Enable PS Remoting
  4.     Enable-PSRemoting -Force
        
  5. Check trusted hosts
  6. In order for you to be able to remotely manage a computer using this method, you must be part of the systems trusted hosts. This serves as a form of access control so that even if a malicious actor gains credentials, they cannot simply remote into the system and start running commands. The next few steps will show you how to manage these trusted hosts.

        Get-Item WSMan:\localhost\Client\TrustedHosts
        
  7. Remove all trusted hosts, if any exist, to allow for a clean slate
  8.     Clear-Item WSMan:\localhost\Client\TrustedHosts
        
  9. Add yourself as a trusted host
  10.     Set-Item WSMan:\localhost\Client\TrustedHosts -Force -Value IP_OR_HOSTNAME_HERE
        winrm s winrm/config/client '@{TrustedHosts="IP_OR_HOSTNAME_HERE"}'
       

    Alternatively you can allow all hosts to PSRemote into this system by setting the "Value" flag to the * wildcard instead of defining a specific IP. This is NOT recommended for security reasons.

  11. Restart the remote management service and make it start at boot
  12.     Restart-Service -Force WinRM
        Set-Service WinRM -StartMode Automatic
        

Setting up the client using PSExec (Windows)

Using psexec, it is possible to remotely execute commands on a system that has the $admin SMB share exposed and open. This is more common than you might think and can be very dangerous. Using psexec, you can run commands as NT/System which is the most powerful user account on a windows computer. This account has more power than the administrator account on your computer. If you are able to use this method without the need for credentials, be aware that a malicious actor will be able to do the same. Passing captured/stolen hashes using psexec is a common tactic used by attackers to pivot to other systems on your network after initial compromise. Unfortunately, I will only cover this from the windows perspective as I have yet to find a modern, working Linux equivalent to these tools. There is the winexe project, but that is outdated and did not work for me on Windows 10 clients. That being said, there are definitely ways to do it from Linux.

In order to get psexec, you need to download PsTools from Microsoft. You will unzip it and find psexec.exe in the extracted folder. After opening a cmd or powershell window and navigating to this folder, you can run the commands from the previous section of this blog just as if you had real physical access to the system using the format shown below.

Without credentials
    psexec.exe \\RemoteComputerGoesHere -s powershell Enable-PSRemoting -Force

With credentials
    psexec.exe \\RemoteComputerGoesHere -u UserName -s powershell Enable-PSRemoting -Force

Opening a remote powershell session

When you are running commands from linux, it is important that you set authentication to negotiate in the flags (as can be seen below). Without this flag, authentication between your Linux machine and the windows machine cannot occur properly.

Save the credentials in a secure environment variable
    $creds = Get-Credential -UserName ADMIN_USERNAME_HERE

Start remote shell with environment variable creds
    Enter-PSSession -ComputerName IP_HERE -Authentication Negotiate -Credential $creds

Start remote shell with username and creds at runtime
    Enter-PSSession -ComputerName IP_HERE -Authentication Negotiate -Credential USERNAME

Invoking commands on a client

Invoke-Command -ComputerName IP_HERE -Authentication Negotiate -Credential $creds `
-ScriptBlock {COMMAND_HERE}

Invoking a PS1 script on a client

Invoke-Command -ComputerName IP_HERE -Authentication Negotiate -Credential $creds `
-FilePath C:\Path\To\Scripts\script.ps1

Managing several clients

You can run either "Enter-PSSession" or "Invoke-Command" with the -AsJob flag and it will run in the background. You will be returned a job id which you can later use to retrieve the job's output using
Receive-Job -id JOB_ID_HERE
If you forgot the job id, you can check it using
Get-PSSession
If you started a background PSSession you can work with it as follows
Accessing session
    Enter-PSSession -id SESSION_ID
Execute command with session
    Invoke-Command -Session (Get-PSSession -id SESSION_ID) -ScriptBlock {COMMAND_HERE}

You can also use other methods such as storing a list of clients in a CSV file or pulling them straight from your Active Directory server.

Running remote commands on several machines from csv of "ComputerName, IP"
    foreach($row in $devices.IP) {
        Invoke-Command -ComputerName $row -Authentication Negotiate `
        -Credential $creds -ScriptBlock{COMMAND_HERE}
    }

Running remote commands on several machines at a time using AD and pipe
    Get-ADComputer -Filter *  -properties name | select @{Name="computername";`
    Expression={$_."name"}} | Invoke-Command -ScriptBlock {COMMMAND_HERE}

Killing background sessions

If you wanted to kill a background session, you would normally run
Get-PSSession -id SESSION_ID | Disconnect-PSSession
However, unfortunately Linux powershell core, at least on 6.2.3, does not have Disconnect-PSSession available as a command. This means that the only way to end a background session is to enter the session and manually type exit. Alternatively you can find and kill the PID of the process.

Where to learn more

There is a lot of information here, some of which may not make sense to you if you have little experience with remote administration over the command line. I highly recommend you start up a windows virtual machine or two and practice the techniques discussed in this post. Additionally, you can use the resources I used to learn the things I am talking about in this post linked below.

Microsoft Powershell Remoting Blog Series
Powershell from Linux