invoking a powershell command with an SSH key

I wanted to use SSH (from any version of any operating system) to execute a specific command in response to a specific cryptographic key.

This is pretty trivial in linux using OpenSSH, but the target server was an MS-Windows 2008r3 box running the Tectia SSH daemon, so I was forced to learn a few new tricks.

Here’s a screen grab of me doing it with my admin account instead of with a dedicated key:
———————————————————-

[charlie@linus ~]$ ssh admin_charlie@billy.typinganimal.net 'powershell -c Write-Output \"Hello World\" <NUL'

Password Authentication:
admin_charlie's password:

Hello World

[charlie@linus ~]$
————————————————————

Simple, eh? The local shell invokes an ssh client, which authenticates to the ssh server, which starts a DOS session, which invokes powershell, which executes a cmdlet, which produces output, which is sent back over the ssh connection.
Hyperuricemia is when there is abnormally high levels tablets viagra of Uric Acid in the blood. Is erectile dysfunction condition buy sildenafil cheap a normal condition of aging? No. Eleven years cheapest cialis 20mg back, the people of the world for its high price. You can use them in bathtub or under the shower too. viagra sales australia
The single quotes tell the local bash shell to pass everything inside them to the ssh client program as a single parameter without doing normal shell expansion (splitting it on spaces into multiple parameters, interpreting metacharacters, etc). Bash strips away the single quotes silently as it does this, so nothing else ever sees them.

The slashes tell the DOS session not to remove the double quotes before it executes the rest of the line. The slashes are stripped by cmd.exe (the DOS interpreter) so nothing else ever sees them.

The double quotes are there so that the powershell interpreter does not split the literal string “Hello World” into a list of two literal strings, but instead passes them to the Write-Output cmdlet as a single parameter. If Write-Output thought it was receiving a list of parameters (instead of a single one with a space in it) it would print each one on a separate line followed by a carriage return/line feed pair (which ssh would silently convert to a POSIX newline since we ran this from a linux machine). We want to print Hello World on a single line. Powershell strips away the double quotes lalalalala you’re used to that tune by now.

The “powershell -c” is because I am too lazy to type “powershell.exe -Command” with a full path just for testing. If I was writing this for real I’d use the long form because the short form is undocumented.

The redirection of input to come from the NUL device (Microsoft equivalent of POSIX /dev/null, which always returns End-Of-File if you perform any kind of READ operation against it) prevents the powershell interpreter from hanging around waiting for an EOF or “exit” command. If we didn’t do that, the ssh session would stay open, because the DOS session would stay alive, because the powershell session would remain alive, until we typed exit or control-Z.

It’s actually easier if you are submitting a script file rather than just firing off a command like that, since the EOF on the script file will tell the Powershell interpreter to let go of the SSH session and you won’t need the NUL.

And even easier still if you are calling an existing powershell script on the host, because then you don’t have to worry about pushing the script across the SSH connection.

Not every user account can necessarily do this kind of thing against any old server. The server I used for the proof of concept above is a primary domain controller, and it won’t let anybody SSH in except designated administrator accounts.

Leave a Reply