Restrict SSH login to a single command

One of OpenSSH coolest features is the ability to force a command for a given SSH access. You can use this to create limited access for demos, monitoring tools, administration tasks and backup process.

Command without arguments

This is the simplest case, you want to restrict the user to a single command without any arguments. This can be achieved with the command= option into the authorized_keys file like this:

command="/usr/bin/command",no-port-forwarding,no-X11-forwarding,no-pty ssh-rsa AAAAB...YrAFnVw== foobar_public_key

Note that in addition to enforcing the command, i also disabled terminal and a number of advanced SSH features, such as TCP and X11 forwarding.

Command with fixed arguments

Same as before, just add the complete chain into the command= block. For example with rsync :

command="rsync --server --delete -logDtpre.iLsf . ~/foobar",no-port-forwarding,no-X11-forwarding,no-pty ssh-rsa AAAAB...YrAFnVw== foobar_public_key

Or if you use rsync in daemon mode:

command="rsync --server --daemon .",no-port-forwarding,no-X11-forwarding,no-pty ssh-rsa AAAAB...YrAFnVw== foobar_public_key

Command with arbitrary arguments

Authorize arbitrary arguments is a little more complicated. This is where the environment variable $SSH_ORIGINAL_COMMAND comes in. When forcing the user command, OpenSSH store the original user command into this variable. By forcing the user to a custom script shell parsing the content of the $SSH_ORIGINAL_COMMAND, you can authorize a specific command with arbitrary arguments:

#!/bin/sh
# /usr/local/bin/limitssh.sh

set -- $SSH_ORIGINAL_COMMAND
case "$1" in
  /usr/bin/command *)
    ;;
  *)
    exit 1
    ;;
esac

exec "/usr/bin/command" "$@"

Then modify your authorized_keys file like this:

command="/usr/local/bin/limitssh.sh $SSH_ORIGINAL_COMMAND",no-port-forwarding,no-X11-forwarding,no-pty ssh-rsa AAAAB...YrAFnVw== foobar_public_key

It is important to be aware of potential security issues here, such as user escaping to a shell prompted from the listed command. Therefore i recommend you to always disable user terminal (no-pty option) and never use this technique with complex ‘command’ like rsync.

Multiple commands

You can modify your bash script to authorize multiple commands instead of one. Keep in mind this solution is kind of a patch-up job and you should really consider using a more robust restricted shell solution instead:

#!/bin/sh
# /usr/local/bin/limitssh.sh

set -- $SSH_ORIGINAL_COMMAND
case "$1" in
	"ps")
		ps -ef
		;;
	"vmstat")
		vmstat 1 100
		;;
	"apache stop")
		/etc/init.d/apache2 stop
		;;
	"apache start")
		/etc/init.d/apache2 start
		;;
	*)
		exit 1
		;;
esac

Erase partition content with dd

If you don’t want or can’t use shred, it’s possible to use dd to erase the content of a partition.

Quick and unsafe method

The first method is to write 0 on all sectors of the disk in a single pass:

# dd if=/dev/zero of=/dev/sdX bs=512 conv=notrunc

Slow and moderately safe method

The second method, a bit more secure than the previous one, is to fill sector with data from the kernel pseudorandom number generator:

# dd if=/dev/urandom of=/dev/sdX bs=512 conv=notrunc

Slow and safe method

Pretty much the same method then the previous one, but this time we will make multiple pass (here 8) :

# for n in `seq 8`; do dd if=/dev/urandom of=/dev/sdX bs=512 conv=notrunc; done