During red team post exploitation I sometimes run into jump boxes leading to test environments, production servers, DMZs, or other organizational branches. As these systems are designed to act as couriers of outbound traffic, hijacking SSH sessions belonging to other users can be useful. So what do you do when you have full control over a jump box and want to leverage another user’s outbound SSH access to tunnel into another segment? What if you don’t have passwords, keys, shouldn’t drop binaries, and SSH is protected by 2-factor authentication? Roll up your sleeves and trust your command line Kung Fu!
This post will cover two approaches to hijacking SSH sessions, without credentials, with the goal inserting dynamic port forwards on the fly. The two stages at which I’ll approach hijacking sessions are: (1) upon session creation, and (2) when a live SSH session exists inside of screen (more common than you’d think). In each case our final goal is to create a tunnel inside another user’s active session in order to gain access to outbound routes on the terminating SSHD host.
Hijacking SSH on Creation:
To hijack newly created SSH sessions we can leverage a feature known as SSH multiplexing. This feature allows for the creation of control sockets that enable an attacker to create their own sessions inside the original user’ socket, without re-authentication. The ControlMaster feature was introduced in OpenSSH 4, and has was previously referenced in H D Moore and Val Smith’s Tactical Exploitation presentation. I also demonstrated the attack in a talk/class of mine entitled, The Poor Man’s Rootkit. In this post I will show two means to force the creation of master sockets, and then how to inject port forwards into them.
ControlMaster via SSH Client Config:
The most common way to deploy ControlMaster sockets is by altering the system wide SSH client config.
|Inserting ControlMaster options into ssh_config on hop_1
These settings will cause all new SSH sessions to create a persistent brokering master socket.
I’ve used %h in control socket commands to represent the target host, %h can be any char(s).
|Master socket created in ControlPath
Connecting to the socket:
This socket can be used to create further sessions, without credentials, even after the original user exits their session.
|Creating a session using a master socket.
Adding a dynamic tunnel:
Remember our end goal is to pivot into other network segments. The following command will create a dynamic tunnel inside an existing master socket.
Dynamic port forward added to live socket
Removing the socket:
Simply exiting the multiplexed sessions will not close the master socket. In order to close the socket you must explicitly send an exit request.
Shutting down the master socket
SSH ControlMaster via Shell Functions:
Another way to leverage this hijacking technique, that I haven’t seen shared before, is by abusing the fact that master sockets may be created through SSH client option flags. As such, we can use a shell function to intercept a user’s SSH client commands and inject our own ControlMaster arguments.
/usr/bin/ssh -o "ControlMaster=auto" -o "ControlPath=/tmp/%r@%h:%p" -o "ControlPersist=yes" "$@";
A simple ControlMaster injecting wrapper function.
This intercepting wrapper function will create sockets identical to those we created using ssh_config.
Successfully injecting ControlMaster options into an SSH client command
Flow of traffic in this attack:
Using SSH ControlMaster sockets and socket options we can now hijack SSH sessions and inject port forwards, all without authentication.
Now to tackle sessions in progress…
Hijacking Active SSH Sessions:
It is not uncommon for users to create screen sessions to house SSH connections to other boxes they are working on. What most users do not realize is that these session can be hijacked and have port forwards injected into them on the fly.Hunting for screen sessions:
One way to find screen sessions is to look under /var/run/screen. Or you can enumerate a single user by issuing an incomplete screen -r command.
Hunting for screen sessions
Bypassing screen pts/tty restrictions:
Accessing the screen sessions of another user is not as straight forward su’ing and viewing; this is where many attackers give up. su to a user to interact with their screen session and you will find yourself staring at one of the following errors: “Cannot open your terminal ‘/dev/pts/#’ – please check.” or “Must be connected to a terminal.”
Error when trying to access another user’s screen session
One way to bypass this restriction is to use the script binary to wrap the su’d user session.
Using script to bypass screen pts/tty restrictions
Adding a tunnel on the fly:
A rarely used feature of SSH is the escape sub-shell. If you are using a means other than SSH to control your access to the jump box you can leverage escape sequences to add port forwards into another user’s established session. Use ~C to drop into the SSH sub-shell, then -D:<port> to add a dynamic forward on the fly. To remove the forward use ~C followed by -KD:<port>
Adding port forwards with SSH escape commands
If you are using SSH for your primary shell the above example will not work from inside screen.This is due to the fact that your own outermost SSH client will catch the escape characters. Not to worry, I’ll show you a way around that!
Creating tunnels with screen stuffing:
Screen has a feature that allows you to “Stuff” the contents of a buffer into its input queue. The stuffed text is parsed as if it had been typed from inside screen, allowing us to bypass escape characters being caught by outer SSH sessions.
Stuffing screen to create a port forward
Stuffing screen to shutdown a port forward
A note on stealthy stuffing: Stuff’d text is visible inside a screen session’s scroll back. You can prevent this by altering the scroll back length on the fly. This can be done by changing the scrollback to 0 lines before your command, clearing the screen, then setting it back.
screen -S my_ssh_session -X scrollback 0
screen -S my_ssh_session -p 0 -X stuff $'~C'
screen -S my_ssh_session -p 0 -X stuff $'-D:9090\nclear\n'
screen -S my_ssh_session -X scrollback 15000
Flow of traffic in screen hijack attack:
Thanks to SSH escapes and screen stuffing we now have a means to hijack established sessions and inject tunnels on the fly!
Tunneling into Remote Segments:
The final step is to bind a local port on our machine to connect us to the tunnel we injected on hop_1.
We now have a full dynamic tunnel into the remote segment, without authentication.
Local port forward on attacker machine via SSH escapes.