How-to build a resilient Raspberry Pi 3 Kali Box
[Disclaimer: The following article is intended for educational purposes only. The information disclosed is meant to be setup in a lab environment or with expressed written permission from relevant owners. Any legal issues resulting from the use of this information, is solely the responsibility of the reader. Any loss of data or damage caused by using any of the information within this article is the sole responsibility of the reader.]
This article is intended to show one of the many options for providing an inexpensive and flexible on-premise penetration testing system. The intended audience for this article is for penetration testers, internal red team testers, security engineers or anyone with the desire to learn new things. Some of the content may be a bit elementary to some of you, however, keep in mind that we all started somewhere and if this gives just one person the spark to get interested in the information security space, the time was completely worth it. At times, some of the concepts many of us take for granted will be explained in greater detail as to provide a more complete picture. The following will be a step-by-step instruction of building, configuring and deploying a system that will create and maintain a continual connection to a specified SSH server. It is important to note that there are many different solutions available for providing a penetration test system, such as a virtual image (OVA/OVF), laptop/desktop, live usb/cd… However, it is this author’s opinion that many of the complications associated with having a customer or third party deploy one of the aforementioned solutions can be avoided by using a pre-configured small form factor system such as Raspberry Pi. There are many small form factor options, however the author has chosen the Raspberry Pi 3 system for it’s cost, large user community and versatility. The only assistance on-site personnel would need to provide for deployment is power and network connectivity. While there are many how-to articles regarding the steps required to build a penetration testing system, this article will focus on not only the build of the machine but the detailed practical configurations, applications and potential pitfalls related to setting up such a system. Finally, additional feature development will be discussed for future functionality and resilience.
Before getting too far into the weeds so to speak, it would be appropriate to discuss why one would even need a dedicated on-site system for penetration testing. First, sending an on-premise system to a customer or geographically remote site in lieu of sending a security professional can drastically reduce the costs associated with travel expenses and time. For the cost of a moderately priced dinner bill ($50-60), a Raspberry Pi and relevant accessories can be purchased. Travel expenses alone for a one week trip start around $1,500 and increase based on distance traveled etc. There may be instances where a customer requires an on site visit, for instance government agencies or highly secure environments that do not permit remote connectivity, in these instances the proposed solution would not be a good fit. For those organizations interested keeping costs down relative to penetration testing and do not have remote access restrictions, an on-premise system is the way to go.
Second, having an on-premise machine provides flexibility for both customer and tester. Once a dedicated system is put in place, logistics regarding physical access are for the most part eliminated. The system detailed within this article will be configured to phone home rather than require the customer to provide remote access such as VPN, relinquishing the need for additional user accounts and configurations. This does not circumvent controls in place by the customer, as the appropriate connectivity will still need to be permitted. As mentioned above, the only requirements to be fulfilled by on-site personnel will be power and appropriate network access including outbound access to the relevant server if agreeable.
This project will consist of building a Raspberry Pi 3 system running Kali Linux 2.0. The method used for the phone home feature includes creating a reverse SSH tunnel to and from a relevant SSH server. The final product will be a headless system, requiring only power and appropriate network connectivity.
The following is a list of items used for this project:
Raspberry Pi 3 with Case and Power Supply
32GB MicroSD Card
Kali Linux image for Raspberry Pi 2/3
SD Card Reader
Mac/*nix/Windows System (to perform imaging and access)
SSH Server
Optional:
2 Dynamic DNS hostnames
1 for the SSH Server
1 for the Kali Linux machine
NOTE: A Mac was used to perform the setup and configuration and some of the commands displayed may reflect as such.
STEP 1 Image Micro SD Card:
Assuming all of the required items have been obtained. The first step in the build process is to image the microSD card. The speed class of the SD card used was 10 and highly recommended by the Kali team. The minimum storage capacity for Kali Linux is 8GB, but the card used for this demonstration was 32GB. Before imaging your new SD card with the Raspberry Pi Kali Linux img file, it is always a good idea to verify the checksums to determine file integrity. This can be accomplished by running the following (* substituted for version):
shasum kali-*.img.xz
Command explaination:
shasum = Built-in *nix utility for calculating checksums for files and strings. The default checksum hash is SHA1, which happens to be the format used on the Kali ARM image download page.
kali-*.img.xz = the file(s) to calculate checksums for.
Compare the output with the checksum specified by the Kali team for the image you downloaded:
If the checksums do not match, the integrity of the file should not be trusted. Try downloading the file again. Rinse and repeat as necessary until you can confirm the integrity of the compressed image file.
Now that the compressed image file integrity has been verified, the img file must be extracted. To extract the image file from the .xz file, use an appropriate compression utility (tar, unxz, 7zip). Using OSX 10.11.4 (El Capitan), the native gunzip or The Unarhiver utility work splendidly for .xz files.
OSX extract command:
gunzip kali-*.img.xz
Linux extract command:
unxz kali-*.img.xz
If you have not already done so, insert your microSD card into the card reader. The next step is determining the microSD card storage device id within the setup system.
For OSX, run the following command to output your storage devices:
diskutil list
For linux, run this command to output your storage devices:
fdisk -l
VERY IMPORTANT: MAKE SURE YOU ARE IMAGING THE MICROSD STORAGE DEVICE. OTHERWISE, YOU MAY END UP IMAGING THE WRONG DEVICE AND CAUSING SIGNIFICANT DATA LOSS.
Make sure you unmount the device as dd will fail due to the device being in use. Here are the commands for unmounting a storage device:
OSX:
sudo diskutil unmountDisk /dev/disk?s?
Note: Using just the device id was not sufficient. Use the more specific partition within the device.
Linux:
sudo umount /<mount point > and or /dev/<device id>
The following is an example of the command used to copy the Kali image to the microSD card.
Both OSX and Linux (parameters in <> are specific to each setup):
sudo dd if=kali-<version>-rpi2.img of=/dev/disk<sdcardid> bs=1m
While the image is being copied (may take over 30 mins) to the microSD card, put together your Raspberry Pi device. Install the Pi board inside the case according to the manufacturers instructions. Purchasing a case is highly recommended, as the components and board can be easily damaged.
Once the dd command is complete, mount the SD card to verify the file system was successfully loaded. This can be done by running a mount command or physically removing the card from the card reader and re-inserting it. Here is an example of the command to run for mounting the storage device:
OSX:
sudo diskutil mountDisk /dev/disk?s?
Linux:
sudo mount /dev/<device id> /<mount point>
Given the file system is intact, the next step of this process is to unmount the microSD card and physically move it from the card reader to the Rasberry Pi device. Use the previously mentioned commands to unmount the imaged storage device.
STEP 2 Harden the System:
At this point, the machine is ready to be configured. There are a couple options regarding the initial setup of the new machine:
- Physically connect to an existing Ethernet network with working DHCP service.
- Connect a keyboard, monitor and mouse and log in locally.
In the case of this build, we want to use this system as a headless unit, meaning the only physical connections required are power and Ethernet. Since, the Rasberry Pi 3 has a built–in wireless interface, once the initial setup is complete, the only physical connection required would be power. Even then, you could completely eliminate all wires with wireless connectivity, battery power and or a consistent form of wireless power (solar, wind, geothermal…really?). While going completely wireless could be useful for some applications, this particular use case will use power and Ethernet.
For this project, the newly built Raspberry Pi 3 was connected to an Ethernet network with a DHCP server providing an automatically assigned IP address after the unit is powered on. If you have access to your DHCP server service, you could determine the IP address that was automatically assigned at startup. Or you could use your network forensics skills to find the new system. Maybe another post going over some basic network forensics is in order but for now, let’s just assume we have access to the DHCP server and we see a new lease for a machine with the name of kali (Kali’s default hostname) and an IPv4 address of 10.1.1.1. Since the SSH server is automatically installed and running for this particular Kali image, the only thing left to do is connect to this machine using your favorite SSH client (native *nix client, Cygwin, putty…) to begin configuration. The following is the command to connect to your running Kali linux instance:
*nix:
ssh [email protected]
The default password for the Kali linux distributions is toor. Once successfully logged in, configuration and hardening is in order. The following sections will be broken out into the different tasks to help harden the OS. Since the device is intended be installed within a remote location (relative to the security professional/tester), physical access makes securing said device a challenge. For the truly paranoid, an attempt will be made to try to discuss the major physical attack vectors.
Full disk encryption:
The first method of hardening any system includes encrypting the entire disk and associated partitions. Unfortunately, for our particular use case, full disk encryption is not necessarily the most advantageous, since it would require authentication prior to OS boot. Perhaps, an interesting project would be to develop a full disk encryption authentication function that would not require user input. While full disk encryption is a good measure to take for system hardening we are going to skip this measure for practicality reasons.
Reset root password:
While passwords are an antiquated form of authentication, they are still very embedded in even the most modern systems to date. In light of this fact, the root password should be changed to a long, complex and pseudo random string. I say pseudo random for all you physicists out there. For our purposes, pseudo random strings will suffice. One of the methods I use to add a little entropy to pseudo-randomly-generated passwords is to change and or add several characters throughout the generated string. It may sound a bit paranoid, but refrain from using online password generators as these strings are coming from an untrusted entity and could potentially be captured/stored/predictable. Use a password generator script or program that can be verified for malicious code. I don’t want to get too far into the weeds regarding password theories, just know that it is very important to have a long (the longer the better) and highly unpredictable string as your password. I have run into situations where the system accepted the an extremely long complex password, but problems arose when using applications against said passwords failed due to input limitations. In conjunction with a password manager such as KeePass, secure copy and paste functions will allow you to limit the attack surface regarding passwords. Yes, for a limited time your password is contained within memory, however, the practicality and convenience of using a copy and paste function supersedes the risks. Think about it, if an attacker has access to your memory, is the use of a password manager copy and paste function any less secure than typing a more than likely weaker password housed in your brain and input through your keyboard. The following is the command to change your password in the vast majority of unix based systems:
passwd
The passwd command used without specifying a username will change the password for the user account running the command.
For completeness, it is important to note that you typically wouldn’t want to run as root on any system, however, an exception is made for penetration testing as many of the tools required also need super admin privileges. The following is the Kali Linux Root User Policy (http://docs.kali.org/policy/kali-linux-root-user-policy ):
Most Linux distributions, quite sensibly, encourage the use of a non-privileged account while running the system and use a utility like sudo when and if escalation of privileges in needed. This is sound security advice: this provides an extra layer of protection between the user and any potentially disruptive or destructive operating system commands or operations. This is especially true for multiple user systems, where user privilege separation is a requirement — misbehavior by one user can disrupt or destroy the work of many users.
Kali Linux, however, as a security and auditing platform, contains many which tools can only run with root privileges. Further, Kali Linux’s nature makes its use in a multi-user environment highly unlikely.
For these reasons, the default Kali user is “root”, and no non-privileged user is created as a part of the installation process. This is one reason that Kali Linux is not recommended for use by Linux beginners who might be more apt to make destructive mistakes while running with root privileges.
Add a less privileged user account:
Adding a low privileged user account serves several purposes, such as restricting SSH access to just this account. By restricting access to a standard user account, a layer is added which increases the necessity for privilege escalation if SSH is ever compromised. This does not go against the Kali Linux Root User Policy as we are simply hardening our administrative access to the system. This system will be going into an unknown and potentially hostile environment, therefore, forgoing simple measures to help prevent abuse is prudent. Again, make sure the password you set for the new account is long and complex.
To create a new user account with just the default privileges, run the following command:
adduser <username>
Rekey SSH public and private keys:
Rekeying the SSH keys, increases the chances of maintaining confidentiality regarding SSH sessions. The public and private keys already configured within the Kali image are not private and should therefore be reset to ensure the SSH private is truly private. Not only should you reset your SSH keys, it’s a good opportunity to increase the bit strength as well. Currently, 2048 bits of encryption are acceptable, however, increasing the bit strength to 4096 provides a much higher level of confidentiality. You never know what kind of information your going to find, so reducing the likelihood of that information is recommended. Take note that increasing the bit strength can also have negative performance impacts. Many of the necessary tasks required for penetration testing do not require an abundance of system resources and those that do (password cracking, decryption…) can be offloaded to more powerful systems. The following are the commands to use in order to rekey the existing SSH keys:
[Run as root]
rm -v /etc/ssh/ssh_host_*
The above rm command, removes all files starting with ssh_host_ within the /etc/ssh/ directory.
Command explanation:
rm = the utility used in *nix sytems to delete files
-v = verbose, outputs what is being removed.
/etc/ssh/ssh_host_* = identifies the files to be deleted. The * wild card is used at the end of the ssh_host_ string means that any file prefixed with ssh_host_ will be identified as input for the associated command.
dpkg-reconfigure openssh-server
This command reconfigures the openssh server to that of the default configuration and re-generates the certificates removed earlier.
Command explanation:
dpkg-reconfigure = Reconfigures debian packages after they have already been installed.
openssh-server = The identified package to be reconfigured.
ssh-keygen -N “” -t rsa -b 4096 -f /etc/ssh/ssh_host_rsa_key
The command above generates new SSH keys per the following modifiers:
ssh-keygen = command used for generating and managing ssh keys.
-N “”= Set a new blank passphrase for the keys to be generated.
-t rsa = Set the key type to rsa.
-b 4096 = Set the bit strength to 4096.
-f /etc/ssh/ssh_host_rsa_key = Generates the SSH key files with the prefix ssh_host_rsa_key within the /etc/ssh/ directory.
[Run as the standard user account from the associated /home/user directory]
ssh-keygen -t rsa -b 4096
This command creates two files within the ~/.ssh/ directory with the names of id_rsa and id_rsa.pub (~ = /home/<username> directory).
Command explanation:
-t rsa = Set sthe key type to rsa
-b 4096 = Sets the bit strength to 4096
You will be prompted for a passphrase to be associated with the keys, however, for convenience and simplicity no passphrase will be configured. Simply hit enter to continue answering the questions regarding the key setup.
Add trusted public keys for clients
vi ~/.ssh/authorized_keys
The above command opens the vi editor (native to *nix) in order to create a file named authorized_keys within the ~.ssh/ directory. The contents of this file should be populated with that of the public SSH keys for trusted users/systems. We will discuss this in greater detail later in the article. The following command can be run on the trusted machines to output the specified keys:
cat ~/.ssh/id_rsa.pub
Command explanation:
cat = outputs the contents of a file to the screen.
~/.ssh/id_rsa.pub = identifies the file to output
Regarding this use case, the above command should be run from the appropriate user account and systems such as the setup computer and the destination SSH server to be used for the reverse SSH tunnel.
chmod 600 ~/.ssh/authorized_keys
The above image shows what your permissions for the authorized_keys file should look like, when looking at the details.
Command explanation:
chmod = The command used to modify file/directory permissions in *nix systems.
600 = Indicates the permissions to be applied:
6 = Read (4) + Write (2) for the owner of the file.
0 = No permissions for the associated group for the file.
0 = No permissions for others (not owner or group member).
~/.ssh/authorized_keys = the file for which the permissions will be applied.
service ssh restart
Command explanation:
service = Command used to manipulate a service or daemon.
ssh = The service to be manipulated. (Some distros it would be sshd)
restart = The manipulative action to be taken against the previously identified service.
The above command can be restarted from an SSH session and will not close or disconnect the existing session.
Reset the hostname of the Kali Linux System:
Renaming the system is not a true hardening technique. However you can better disguise the system, immediately outing the system as kali identifies the purposes for penetration testing quite obviously. In some instances, the kali hostname will be sufficient; this is just another measure to help stay quieter. As the Backtrack/Kali mantra goes “The quieter you become the more you are able to hear.” The following are the commands needed to change the system hostname:
hostname <new_hostname>
Command explanation:
hostname = command used to show or set the system hostname
<new_hostname> = The new hostname the system will be set to.
vi /etc/hosts
Modify the line within the hosts file that specifies kali with the hostname you have selected.
Test connectivity from a trusted machine using SSH PKI for authentication:
This step requires the appropriate id_rsa.pub string to be populated within the ~.ssh/authorized_keys file for the standard user created in the steps above. The following is an example of a connection to the Kali linux machine from an authorized user/system:
ssh [email protected]
Command explanation:
ssh = Command used to invoke the SSH client.
[email protected] = The user account to be used at the destination IP address of the system to be connected to. In this case, our new Kali Linux Raspberry Pi 3 machine. Given the appropriate public keys have been added to the previously mentioned authorized_keys file, a new session to the Kali system will be established, dropping you in the lowprivuser’s home directory (/home/lowprivuser).
The last step of testing would be to change to the root user context by running the following command:
su –
Command explanation:
su = The command used become another user within an already logged in session.
– = Indicates opening the new user account using environment variables similar to those that would be applied if logging in locally as said user.
Since there is no username specified, it uses the default user account of root. The command above is the same as running su – root. But for efficiency sake, we can drop off specifying root as it is unnecessary.
Now that the SSH public key authentication has been tested and verified successful, the SSH server configuration can be hardened a little more than it already is. The reason you want to test your authentication thoroughly is that you could potentially lock yourself out of the system requiring the reversal of the following changes if problems are experienced.
Harden SSH server in /etc/ssh/sshd_config:
AllowUsers lowprivssh
PermitRootLogin no
ChallengeResponseAuthentication no
PasswordAuthentication no
# Message Authentication Code (Hash, only SHA2-512)
MACs hmac-sha2-512
# Ciphers (only secure AES-256)
Ciphers aes256-cbc,aes256-ctr
# Key Exchange algorithms (Elliptic Curve Diffie-Hellman)
# DH-SHA-256 included for compat with PuTTY-WinCrypt clients
KexAlgorithms ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256
Parameter explanations:
AllowUsers lowprivssh = Allows only the lowprivssh account to connect to the SSH server. Users can be specified in a space separated syntax (lowprivssh user1 user2 …)
PermitRootLogin no = Do not allow the root user account to login via SSH. The AllowUsers parameter should take care of this but disabling root from logging in directly deserves a mention.
ChallengeResponseAuthentication no = Does not allow challenge-response such as those used within the login.conf configuration (PAM, RADIUS, LDAP…)
PasswordAuthentication no = Does not allow the use of username and password authentication.
MACs hmac-sha2-512 = Uses on the SHA2 512 bit hashing algorithm for establishing SSH connections. For more information on the SHA2-512 hashing algorithm can be found here: https://en.wikipedia.org/wiki/SHA-2
Ciphers aes256-cbc,aes256-ctr = Only allows the use of AES256 cipher block chain and AES256 counter ciphers are allowed for establishing SSH sessions. The reasons these two cryptographic ciphers are used is out of the scope of this article. For more interesting reading regarding these ciphers can be found here: https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation
KexAlgorithms ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256 = The only key exchange algorithms to be used for establishing SSH sessions are Elliptical Curve Diffie-Hellman SHA2 on the nistp521 curve and the diffie-hellman-group-exchange-sha256 method. For more information regarding these to algorithms see:
https://www.ietf.org/rfc/rfc5656.txt
http://tools.ietf.org/html/rfc4419
Once all of the above sshd_config parameters have been added/modified, a restart of the ssh services are necessary.
service ssh restart
Suffice it to say that there are many more hardening measures you could take regarding SSH server configuration but the above should be good enough for this particular use case.
STEP 3 Configure Automated Phone Home:
Now that the basic framework is setup for this machine, we can now start bringing the phone home capabilities into the picture. Before we start discussing the configuration, let’s talk about how the system is going to know how to establish a connection back to home base. Essentially, the only requirements for establishing a reverse SSH tunnel is:
1) The FQDN or IP address of the home SSH server.
2) Access to the relevant SSH server from the client site.
3) The appropriate configuration for autossh.
For this demonstration, we are going to define the requirements as follows:
Home SSH Server FQDN/IP = homessh.example.com/1.1.1.1
Assumptions:
1) The home server infrastructure allows connections from clients from anywhere in the world. Preferably, this server would sit in a very restrictive DMZ as it will be internet facing. We will discuss ways to reduce the attack surface for this server but for now we will simply make the assumption that it connectable from any relevant IP address.
2) The home SSH server has been built and hardened using the same parameters mentioned regarding the Kali linux SSH setup.
3) Assume this is a minimalist build providing only the services required for this use case.
4) The Kali box is going to have the relevant access allowed from the customer site to the home server.
5) A stable Internet connection exists between both the customer and home server.
Given the above definitions and assumptions, we can move onto setting up the reverse SSH tunnel(s). There is a great write-up and how-to here https://raymii.org/s/tutorials/Autossh_persistent_tunnels.html. Luckily, most of the items required have already been configured to this point. The last step in this project is to setup and make resilient the autossh package. According to it’s man page, autossh is described as follows:
autossh is a program to start a copy of ssh and monitor it, restarting it as necessary should it die or stop passing traffic.
The original idea and the mechanism were from rstunnel (Reliable SSH Tunnel). With version 1.2 of autossh the method changed: autossh uses ssh to construct a loop of ssh forwardings (one from local to remote, one from remote to local), and then sends test data that it expects to get back. (The idea is thanks to Terrence Martin. With version 1.3, a new method is added (thanks to Ron Yorston): a port may be specified for a remote echo service that will echo back the test data. This avoids the congestion and the aggravation of making sure all the port numbers on the remote machine do not collide. The loop-of-forwardings method remains available for situations where using an echo service may not be possible.
We are going to use autossh as the mechanism for our Kali Linux box to connect back to our home SSH server and attempt to maintain a persistent connection. By default, the autossh package is not installed on the Raspberry Pi 2/3 Kali Linux image making it necessary to install the necessary packages. The following is the command used to install the autossh package on Kali Linux:
[Run as root]
apt-get install autossh
Command explanation:
apt-get = The command invoking the standard package manager program for Debian based linux operating systems (Debian, Kali, Ubuntu…) which facilitates the necessary functions such as installing, updating and removing packages.
install = The apt-get command modifier indicating installation of the subsequently specified packages.
autossh = The package we want to install. More packages can be added using a space separated syntax (<package_1> <package_2>…<package_n> ).
Now that autossh is installed, the next logical step is to configure it. This is actually quite simple since we know where our initial connection is destined (the home SSH server). Keep in mind, the commands and scripts for the following are only examples. You can make your commands and scripts as elaborate and resilient as you would like but for brevity sake, functionality will be the key for this script. The following is a simple command regarding establishing a reverse ssh tunnel using auto ssh (not persistent):
autossh -nNT -o ServerAliveInterval=15 -R 6666:localhost:22 [email protected] &
Command explanation:
autossh = The primary package that will help maintain the reverse SSH tunnel for connectivity.
-nNT:
-n = Redirects stdin from /dev/null (actually, prevents reading from stdin). This must be used when ssh is run in the background.
-N = Do not execute a remote command. This is useful for just forwarding ports (protocol version 2 only).
-T = Disables the default pseudo-tty allocation. This is important to disable as we are scripting the SSH session and will not require the standard input output (stdin/stdout, e.g. keyboard, screen…).
-o ServerAliveInterval=15 = This parameter enables the option to send server keep alive messages every 15 seconds, in order to maintain the session.
-R = This is the option that actually facilitates the setting of up the reverse tunnel.
6666:localhost:22 = This string identifies TCP 6666 as the port to listen to on the server side: localhost (127.0.0.1) is identified as the host /IP address to bind to: TCP 22 as the remote (Kali host) port to be forwarded to over the existing tunnel.
[email protected] = This is the standard input you for connecting to any ssh server (<user>@<hostname/IP).
& = Opens the SSH session in the background. Note: If this modifier is not entered, the established session is contingent upon your existing session from which you are running the command.
If this command is successful, you can verify the appropriate connectivity is available by running the following:
[Run on Home SSH Server]
netstat -an | grep ‘:6666 \| 10.1.1.1:22’
Command explanation:
netstat = command used to display the status of various network states.
-an = Options used to display all (-a) network listeners/connections in number (-n) format.
| = Passes the output (stdout) of a previous command to the input (stdin) of the next one, or to the shell. This is a method of chaining commands together.
grep = The defacto search tool in *nix for finding specified strings or regular expressions (regex).
‘:6666 = Searchs the output for any lines that contain :6666. If identified it will display all lines in the output that contain the string :6666.
\| = Indicates a grep OR, meaning it will look for the previous string or the next string you pass to it.
10.1.1.1:22’ = The second parameter that grep will search for through the netstat output, as it is the string that follows the grep OR option. This string should filter output that shows all SSH sessions regarding the home server IP address.
The following is an example of the output that should display (Assume your local administrative client machine IP is 2.2.2.2):
tcp 0 0 127.0.0.1:6666 0.0.0.0:* LISTEN
tcp 0 0 1.1.1.1:22 10.1.1.1:59751 ESTABLISHED
tcp 0 0 1.1.1.1:22 2.2.2.2:41820 ESTABLISHED
tcp 0 0 ::1:6666 :::* LISTEN
If you are able to verify that the appropriate sessions are established for using the reverse tunnel, use the following command to connect to the Kali linux machine via the reverse tunnel:
[Run from an SSH session on the home SSH server]
ssh -p 6666 lowprivssh@localhost
Command Explanation:
ssh = Command to invoke the ssh client on *nix systems.
-p 6666 = The TCP port (6666) to be used when connecting to the SSH server.
lowprivssh@localhost = Username at the destination server to be connected to. Since the reverse tunnel is listening on the localhost (loopback IP) over TCP 6666, all connections to TCP 6666 will be forwarded to the Kali Linux machine.
Since we hardened the Kali SSH server, public key authentication is the only way to login. If the appropriate public keys are not populated within the ~.ssh/authorized_keys file of the user account, authentication will fail. Once logged in, we can use the following command to login to the root environment:
su –
To help visualize what is happening here is a text diagram of what has happened to get this to work:
1) Kali →Home SSH server:22 (Also, creates reverse tunnel listener on localhost:6666)
2) Tester_machine → Home SSH server:22
Home SSH Server → Kali (over reverse tunnel 6666:localhost:22)
Given authentication success, session established with Kali SSH server.
Hopefully, the above explains the reverse tunnel in a nutshell. Now that we have verified that the reverse tunnel is fully functional, implementing some persistence to this tunnel is necessary. Before moving forward let’s kill the current sessions and autossh processes.
[Run as root on Kali machine]
pidof /usr/bin/ssh | xargs kill -9
Command explanation:
pidof = Native command for looking up process IDs within unix.
/usr/bin/ssh = The path of the command we are looking for to stop/kill. You could simply put autossh in lieu of he full path to ssh, however, it appears that when specifying the parent process the child processes remain intact. By killing all of the processes using /usr/bin/ssh, autossh is included killing all necessary ssh processes. Using this parameter on an SSH server/client that needs to maintain other ancillary connections using port forwarding and the like, you may want to simply identify the relevant processes and kill them specifically.
| xargs kill -9 = This takes the arguments passed on by pidof and applies the kill -9, which will kill all of the relevant process IDs regardless of their state.
Configure for persistence:
By no means will the following be the only way this can be done. This is what worked at the time of this writing and should be taken with a grain of salt. Up until now, pretty much all of the steps have utilized only command logic devoid of any custom scripting. Unfortunately, the autossh package and existing SSH configurations did not behave with the anticipated resilience, even when scripting the autossh to start at boot. As luck would have it, whilst writing this post, a storm rolled through and caused the test Kali Linux box to restart and or crash, as it was not connected to an uninterruptible power supply. Even though reboot testing and the like had been performed successfully (probably not as thorough as should have been), in this instance, the reverse tunnel had not re-established. Further investigation showed two major problems were revealed:
1) The autossh process was attempting to start prior to the server obtaining a DHCP assigned IP address, essentially terminating and never attempting again.
2) The home SSH server, was not closing connections that were not gracefully shutdown. The sessions showed established for well over 30 minutes after the connection had been lost.
Luckily, the above conditions were overcome by implementing a little bit of help in logic and SSH server reconfiguration. The following are the steps taken to maintain and or re-establish SSH tunnels to/from the home SSH server.
First we want to help ensure that autossh is turned up after a reboot and or power failure. Two scripts were used to accomplish this task:
[On Kali Machine]
1) /etc/rc.local
2) Custom bash script placed in /etc/init.d/autossh.sh
The rc.local file is typically not used but is run once when the system is booted. Since this script already runs at boot time, we don’t have to worry about applying the necessary configuration changes to get the custom script to run at boot. Additional logic can be added as well if so desired. The following is the output of the example /etc/rc.local script (additions in green):
vi /etc/rc.local
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will “exit 0” on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
sleep 600
/etc/init.d/autossh.sh
exit 0
Notice the sleep command; this waits 10 minutes before attempting to run the autossh.sh script. This is an attempt to allow a network connection to be established prior to starting autossh, which according to the default behavior relevant to the scripted command, terminates the autossh process and never attempts a connection again.
Now to start our autossh process as well as make sure it remains running, a custom script was used to accomplish this. There is much more that could be added but this example should suffice for our purposes. The following is the script used for starting and maintaining the autossh reverse tunnel to/from our home server:
vi /etc/init.d/autossh.sh
#!/bin/bash
#Define variables
svc=’autossh’
DATETIME=$(date “+%B %d %H:%M:%S”)
# If statement where the condition is based on whether the variable svc is running.
pidof $svc
if [ $? != 0 ];then
#If the service is not running perform the following actions
echo “$DATETIME $HOSTNAME $svc is not running, attempting to connect home.” >> /var/log/messages
autossh -nNT -o ServerAliveInterval=15 -R 6666:localhost:22 [email protected] &
fi
# If the service is running, nothing is performed. Adding an else statement above, would allow for doing something regarding that condition if required.
The last step in making sure this remains resilient, is to schedule the /etc/init.d/autossh.sh script in cron.
[From the root account on the Kali machine]
crontab –e
Command explaination:
crontab = According to the crontab man page, it is the program used to install, deinstall or list the tables used to drive the cron(8) daemon in Vixie Cron.
-e = Facilitates the editing of cron.
You may be prompted for a request to specify your editor of choice, (nano or vim). Select the text editor you are most comfortable with. Once you have opened cron using the root user account add the following line to the end of the file if you want to check the maintain the reverse tunnels built by autossh:
* * * * * /etc/init.d/autossh.sh
Crontab line explanation:
* * * * * = The 5 stars represent (min, hr, day, week, month) the schedule to run at the subsequent script at the top of every minute of every hour of every day of every week of every month.
/etc/init.d/autossh.sh = The script to be scheduled.
You don’t have to run the script every minute, just know that the longer you wait between verification the longer it will take to re-establish lost sessions. More information regarding scheduling tasks in cron can be found here:
http://crontab.org
The following are some verification steps to be taken to make certain your build is resilient (connection wise):
1) Monitor sessions using the aforementioned netstat command on the home SSH server to determine when the reverse tunnel re-establishes.
a) Run pidof /usr/bin/ssh | xargs kill -9 on the Kali box and verify if your tunnel is re-established.
b) Reboot the Kali box and see if your tunnel is re-established.
c) Disconnect the Kali box from the network for several minutes and verify if your tunnel is re-established.
d) Pull the power from your Kali box, wait a few seconds, power up and verify if your tunnel is re-established.
If all of the above tests are successful, your system exhibits resilience. You now have a setup that can be utilized for practical purposes, such as an inexpensive and easily deployable penetration-testing platform for multiple purposes (in our case, to play).
In the spirit of being thorough, the following are some interesting additions to this project:
1) Provide a secure means for full disk encryption without requiring human authentication.
2) If not using static IP addressing, add a dynamic DNS agent and FQDN to help identify the associated Kali machine.
3) If no network connection is established, configure wifi to automatically connect to any open networks.
a) Set a preference for Ethernet over Wifi.
b) Write program or bash script to attempt to crack wifi, starting with weakest available to strongest. Once cracked and credentials are stored, connect to said network, loop until successful, upon disconnect, resume wifi cracking.
4) Automate network discovery with NMAP.
The automation possibilities are seemingly endless. Hopefully, this article hasn’t muddied the waters too much so to speak and you had fun with it.
Helpful links:
http://www.amazon.com/s/ref=nb_sb_noss_2/177-2361236-4848657?url=search-alias%3Daps&field-keywords=raspberry+pi+3
https://www.offensive-security.com/kali-linux-arm-images/
http://docs.kali.org/downloading/kali-linux-live-usb-install
https://www.howtoforge.com/reverse-ssh-tunneling
http://www.cyberciti.biz/faq/howto-regenerate-openssh-host-keys/
https://gmorehou.wordpress.com/2013/10/26/change-ssh-host-keys-raspbian-cubian-premade-linux-virtual-machines/
https://raymii.org/s/tutorials/Autossh_persistent_tunnels.html
http://www.tecmint.com/command-line-tools-to-monitor-linux-performance/
http://www.hacking-tutorial.com/tips-and-trick/how-to-send-email-using-telnet-in-kali-linux/
https://help.dyn.com/ddclient/
http://souptonuts.sourceforge.net/postfix_tutorial.html
http://www.cyberciti.biz/tips/linux-unix-bsd-openssh-server-best-practices.html
http://www.brennan.id.au/12-Sendmail_Server.html
https://www.sdcard.org/developers/overview/speed_class/
http://docs.kali.org/kali-on-arm/install-kali-linux-arm-raspberry-pi
http://docs.kali.org/policy/kali-linux-root-user-policy
https://en.wikipedia.org/wiki/Chmod
https://www.freebsd.org/cgi/man.cgi?sshd_config%285%29
https://www.freebsd.org/cgi/man.cgi?query=login.conf&sektion=5&apropos=0&manpath=FreeBSD+10.3-RELEASE+and+Ports
https://en.wikipedia.org/wiki/SHA-2
https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation
https://wiki.tools.ietf.org/id/draft-ietf-curdle-ssh-kex-sha2-02.html
https://www.ietf.org/rfc/rfc5656.txt
http://tools.ietf.org/html/rfc4419
http://askubuntu.com/questions/157779/how-to-determine-whether-a-process-is-running-or-not-and-make-use-it-to-make-a-c
https://www.godaddy.com/help/how-to-set-an-ssh-timeout-12300
http://linux.die.net/man/1/ssh
http://man.openbsd.org/ssh
http://tldp.org/LDP/abs/html/special-chars.html#PIPEREF
http://crontab.org/