Friday, August 22, 2008

Restrict SSH to Run A Specific Command

You may know that if you were to include your ssh public key in the remote host's authorized_keys file, you can ssh/scp into that remote machine without password login. This will enable administrator to program script to run without having to interactive with it.

However, not everyone know (I did not know at first) that you can restrict (or force) the ssh session to just execute a particular command. Below shows you how to generate a specifiy public/private key pair (monitoring, monitoring.pub), include the monitoring.pub public key in the remote authorized_keys and prepend that with "command=....". So next time you ssh into this remote machine with the monitoring key using the -i flag, the remote system will automatically run the command.

I used this technqiue to run some of the monitoring scripts installed across a few remote servers. This provides some form of flexiblity without compromising security.

myhost:

chihung@myhost$ cd ~/.ssh

chihung@myhost$ ssh-keygen -t rsa -f monitoring
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in monitoring.
Your public key has been saved in monitoring.pub.
The key fingerprint is:
6c:00:82:a5:b1:38:c0:e1:83:e3:c1:7d:82:48:d2:12 chihung@myhost

chihung@myhost$ cat monitoring.pub
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAwyAsd3AkcO2Oi3nN71WCTdSg/HXlyA3m74TBqSiAygE7XanwiyhpspFHtM3QFZhZRoqTjUyXwC1qbJyD2fNA2U7JtxBU1x5FCcDoLEIzVR4qplAN5cVFrN7SS4Ee49RRLDVdVV+RIGZdiDe9dqGfaVAKi1pqmvsDJez8AnjAg0U= chihung@myhost

remote:

chihung@remote$ cd .ssh

chihung@remote$ cat authorized_keys
command="/usr/local/bin/my-monitoring.sh" ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAwyAsd3AkcO2Oi3nN71WCTdSg/HXlyA3m74TBqSiAygE7XanwiyhpspFHtM3QFZhZRoqTjUyXwC1qbJyD2fNA2U7JtxBU1x5FCcDoLEIzVR4qplAN5cVFrN7SS4Ee49RRLDVdVV+RIGZdiDe9dqGfaVAKi1pqmvsDJez8AnjAg0U= chihung@myhost

chihung@remote$ ls -l authorized_keys
-rw-------  1 chihung chihung  264 Aug 19 21:37 authorized_keys


chihung@myhost$ ssh -i ~/.ssh/monitoring chihung@remote
...
...

PS. Thanks to Ben who highlighted the security loophole in the remote authorized_keys. See comment

Labels: ,

8 Comments:

Blogger Ben Noordhuis said...

Correct me if I'm wrong, but won't:

scp my_crafted_authorized_keys yourhost:~/.ssh/authorized_keys

allow me to circumvent your restrictions if authorized_keys is writable? The command="{command}" won't be executed until SSH spawns a shell, but the scp copy takes place before that.

http://www.snailbook.com/faq/restricted-scp.auto.html

10:00 PM  
Blogger chihungchan said...

Hi Ben, you are right. Thanks for highlighting this.

9:25 AM  
Blogger Piavlo said...

Is it possible to pass arguments to the command from the ssh client?

5:21 PM  
Blogger chihungchan said...

I don't think you can pass argument, may be you can look it up in the man page. Please let me know if you can find a way to do that

8:20 AM  
Blogger yungchin said...

I just tested Ben's proposed circumvention, and it doesn't work - at least not with SSH2 (but I don't suppose anyone is using SSH1 in 2008/2009). In fact, it says as much in the sshd manpage: "Note that this option applies to shell, command or subsystem execution." While scp does not spawn a shell, it does need to run scp on the server, and that won't happen.

@piavlo: by now you've probably found your answer, but yes: you can execute interactive commands which ask input from the client (I just tested this by setting command="python" in authorized_keys...).

3:58 AM  
Blogger chihungchan said...

Thanks YC.

Just tested in running an interactive shell successful, what piavlo is asking is command line argument which I don't think is possible. Any clue in doing that

10:30 PM  
Blogger yungchin said...

Well I was thinking along the lines of creating an interactive script (server-side) that asks for the parameters - of course it has to be a very smart script, that doesn't allow code-injection...

So you run a script client-side, that opens an ssh connection, and then the server-side script asks the client-side script to pass it parameters. Not easy, but possible.

10:39 PM  
Blogger Trent Nelson said...

You can do the following to pick up command line args:

command="/foo.sh $SSH_ORIGINAL_COMMAND" ssh-rsa

foo.sh will then be passed with all the arguments you invoke ssh with on the other machine, i.e. ssh abcd efgh

$1 = abcd, $2 efgh

2:37 PM  

Post a Comment

<< Home