Summary:Introducing Authprogs, software which lets you control which
machines can run authorized commands via SSH using SSH Identities.

In the previous three[1]
articles, I've shown you how to manually set up identity-based
authentication with SSH, and how to use it to force a specific
command, regardless the actual command that the client attempts
to run. Unfortunately, this procedure requires that you have
one identity for each program you want to allow, which can be
a very big hassle.

In this article, I introduce you to authprogs, which
can be used to control what
commands can be run on a host-by-host basis.
I've been using this program for ages now, and finally
took the time to put in comments and make it readable.
I'll be maintaining the code at http://www.hackinglinuxexposed.com/tools/authprogs.
There are several things left to be done[2] and I encourage folks to develop it further.
Right now I'd call it version 0.5.

Authprogs is a very simple perl script.[3] It looks
for a file named ~/.ssh/authprogs.conf to get its configuration.
This file simply lists the programs that are allowed to be run
from specified hosts. You begin with an IP address or
list of IP addresses in brackets. On the following lines you
put the commands that are allowed from this host or hosts.
Here's an example configuration:

In this case, any machine (ALL is a wildcard for any machine) can
run uptime. The machine 127.0.0.1 (localhost) can
run /bin/ls /tmp[4]

In the third section, we list an rsync command that can
be run by two machines. You could have created a separate
section for 10.0.0.256 with this rsync command, and copied
the command in the previous entry for 127.0.0.1, but this is
a bit cleaner, depending on your needs.
The entire file is read until a match is
found, so you can have multiple sections for a given
host.

As you see in the fourth section, if you need
to allow spaces in your command arguments, just use
double or single quotes normally. You can also
put comments on their own line anywhere in this
file, as long as you have them on their own line.

Lastly, it's completely fine to have multiple commands
on one line, or even shell meta-characters. For example
if the user from 172.31.282.10 wanted to run the authorized
command above, they'd run the following:

The quotes here are needed to make sure that the local shell
doesn't expand *.html or execute the
rm and wmk locally. All the commands
to be run on the server must be passed through unaltered.

So, how do you install the authprogs program? You can put
it in your ~/.ssh/ directory, or install it system wide
in /usr/local/bin, or anywhere else you want. Just make
sure to chmod a+rx it when you're done. Then
set up your authorized_keys to run authprogs
using the command= option in your authorized_keys
file, create a ~/.ssh/authprogs.conf file, and you're all set.

Ok, so that's a long list. We'll walk through it.

Let's craft an example similar to the one from last week.
The host beepbeep.example.net is our backup server. It wants
to run the following program to back up the /etc/ directory
on host futzy.example.net:

backups@beepbeep$ cat backup_futzy
#/bin/sh
# Go into our backups directory for futzy
cd /backups/futzy/etc
# Tell rsync to use ssh with a specific key. The key we
# created for this purpose is stored in /home/backups/keys/futzy
RSYNC_RSH="ssh -i /home/backups/keys/futzy"
export RSYNC_RSH
# Sync the etc directory to a local backup.
rsync -logptr root@futzy.example.net:/etc/ .

Let's set up futzy to allow the rsync command to succeed. First,
install authprogs:

We added several "no-" arguments to turn off SSH features this
key doesn't need access to, and then the crucial "command="
argument which will force our authprogs command to run. You may
notice that I left off the "from=" option which could
have been used to limit this key to work only from specified hosts.
You can either use it or not as you choose. The authprogs program
will drop unauthorized commands or unauthorized hosts, so it's not
strictly needed.

Now we haven't set up our authprogs.conf file yet, so the rsync
command should fail. Let's run it for grins:

The authprogs program actually shoots an error to STDERR (the "You're not allowed..."
line above) to let the client know the command is rejected. You can use this
error to determine what command was sent, and add this command to the
authprogs.conf file.

However, the authprogs program also keeps a log of the commands
that are attempted. Looking at the log, we can see which commands
were run, and which were denied:

This log entry indicates that the machine 192.168.25.10 (beepbeep's
IP address) tried to run the command "rsync --server --sender -logtpr . /etc/".
The two numbers 53251 and 22 at the end of the line indicate the
source and destination port of this SSH connection, and aren't terribly
interesting.

So, armed with the knowledge of the command rsync is
attempting to run on the server, let's set up our authprogs.conf
file:

Now the beauty of authprogs is that you can use this key for many
different commands, without ever allowing it to have unrestricted
access to the system.[5] It
also means you have one file to maintain which lists the hosts
that can run specific commands without a password.

You can use the same private key on multiple machines, because the
authprogs.conf file still dictates which commands a machine can run.
However I still prefer creating unique keys on each client that
needs passwordless access, just to be safe. Reusing keys doesn't
buy you much.

In summary, the authprogs program is a very simply way to
create passwordless access to accounts with fine granularity. Unlike
custom shells, it is usable on any account. (You wouldn't want to
change root's shell to something that only allowed you
to run "hostname" for example.) There are some obvious
areas it could be improved, but it works as advertized.

[5] Of course you should really avoid having
any shell meta-characters or backticks available in your allowed commands,
lest an attacker manage to trick them into running commands you didn't
think of. Explicit commands are not prone to this sort of trickery,
and are your best bet to keeping things secure.

Bri Hatch is Chief Hacker at Onsight, Inc and author of Hacking Linux Exposed and Building Linux VPNs.
He's been using SSH to secure his remote
logins since Tatu posted the first version of the code - even if the
administrators of those machines refused to install it for him.
Bri can be reached at bri@hackinglinuxexposed.com.