SSH Hijacking for lateral movement
A few weeks ago I contributed the SSH Hijacking lateral movement technique to MITRE’s ATT&CK framework. In this post I’ll go through the different implementations of this attack that I have come across so far to provide more details around it. Note that by hijacking here we mean that someone abuses the existing sessions without having access to the authentication details. So, without using stolen credentials or private keys.
ControlMaster
SSH’s ControlMaster is a feature which allows multiplexed connections. Performance wise this is great since you only have to authenticate to the target system on the first SSH session and then, depending on the SSH daemon configuration you can open multiple new SSH sessions through the already established connection. This can be tuned on the server side with the following two directives.
MaxSessions Specifies the maximum number of open sessions permitted per network connection. The default is 10. MaxStartups Specifies the maximum number of concurrent unauthenticated connections to the SSH daemon. Additional connections will be dropped until authentication succeeds or the LoginGraceTime expires for a connection. The default is 10.
By setting MaxSessions to 1 you can disable ControlMaster/session multiplexing and each new session will require a complete new connection that includes the authentication step. However, if you don’t, then regardless of how strong authentication method you are employing for your users, an attacker only has to get code execution to one of your user’s endpoints and wait for that user to SSH somewhere. The attacker can look for the open connections by inspecting the directory specified by ControlPath directive on the client’s side or just using common tools like netstat. Then, if the attacker attempts to open an SSH session to a host that it is already in the ControlMaster, it will require no authentication or establishing a new connection as it is re-using the existing one. Note that ControlMaster is enabled by default.
Agent Authentication
To reduce friction and make the experience more smooth many organizations employ the use of SSH-agent which is a service that allows authentication via a local socket file. When you connect to a remote system you can choose if you want your ssh-agent to be available there too using the ForwardAgent directive. By forwarding the agent you can move around systems without having to copy keys everywhere or re-authenticating manually. However, this has a downside too. If an attacker has root access on any of the systems from which you have forwarded your agent, he can re-use that socket file to open new SSH sessions with your information. Here is a very brief overview of how this is done.
# Attacker finds the SSHd process of the victim ps uax|grep sshd # Attacker looks for the SSH_AUTH_SOCK on victim's environment variables grep SSH_AUTH_SOCK /proc/<pid>/environ # Attacker hijack's victim's ssh-agent socket SSH_AUTH_SOCK=/tmp/ssh-XXXXXXXXX/agent.XXXX ssh-add -l # Attacker can login to remote systems as the victim ssh remote_system -l vicitm
If you are using OpenSSH, you can mitigate this threat by using the AllowAgentForwarding directive to ensure that only the hosts that need it will have it, rather than the entire environment.
In both of those cases, the attacker never had direct access to the authentication details. However, by abusing SSH features an attacker is able to move laterally into the environment without causing a lot of noise. I already gave some native SSH directives that can be used to mitigate this threat but of course, depending on your requirements you might have to come up with something different.
Leave a Reply