There are situations when a friend is in need of Linux help, and the only way for you to help them is to log in to their machine and fix the problem yourself, instead of trying to explain over the phone all the steps to your friend.
Such a problem has two sub-problems:
- The remote machine must accept incoming connections and provide you with shell access. The obvious way to achieve this is an SSH daemon. Many Desktop Linux distributions don’t install an SSH server by default though, for security reasons. Setting up an SSH server in this moment is slow, and could even not be possible, if your friend messed up with the packaging system, for example. So we need to find an easy way to bind a network shell on the remote machine.
- We must be able to connect to the remote machine. Usually desktop machines are protected behind a firewall or NAT, and we cannot connect to them directly. If this is not the case for you, you can skip this step and just connect to the remote machine IP address. A common approach to overcome this problem is that the remote machine connects to a machine of yours, which has an accessible real IP address and has a running SSH server. Most Desktop Linux distributions have an SSH client installed by default. So all you need to do is quickly and temporarily set up an account with password authentication for your friend on your machine. Then let them log in there which will create a reverse tunnel back to their machine.
Bind a shell
Another useful tool which is usually available on Linux is the Netcat, the Swiss-army knife for TCP/IP. In order to bind a shell using the Netcat version available on Ubuntu/Debian, you need to execute the following:
mkfifo /tmp/mypipe # user shell cat /tmp/mypipe|/bin/bash 2>&1|nc -l 6000 >/tmp/mypipe
I got this awesome idea from a user comment. I only extended it a bit by adding “2>&1” which redirects the STDERR error messages to the remote network client too.
Once the above has been executed on the remote machine, anyone can connect on TCP port 6000, assuming that there is no firewall. Note that you have to connect via Netcat again. A connection via Telnet adds an additional “\r” at every line end, which confuses Bash. If you need to perform actions as “root” on the remote machine, the shell needs to be executed as “root”:
mkfifo /tmp/mypipe # root shell cat /tmp/mypipe|sudo /bin/bash 2>&1|nc -l 6000 >/tmp/mypipe
If you are worried that your friend will mistype something, save the commands to a text file on a web server, and let them download it using “wget” or “curl”. Example:
wget http://www.famzah.net/download/bind-shell.txt # or curl http://www.famzah.net/download/bind-shell.txt > bind-shell.txt chmod +x bind-shell.txt ./bind-shell.txt
Reverse connect using an SSH tunnel
The ssh client has the ability to forward a local port (review Reversing an ssh connection for a detailed example). Once you’ve set up an account for your friend, you ask them to connect to your machine:
ssh -R 6000:127.0.0.1:6000 $IP_OF_YOUR_MACHINE
Once your friend has connected to your machine, you can connect to theirs using the reverse SSH tunnel by executing the following:
nc 127.0.0.1 6000
The connection to 127.0.0.1 on TCP port 6000 is actually forwarded by SSH to the remote machine of your friend on their TCP port 6000.
Note that once you disconnect from the “nc” session, the Netcat server on the remote machine exists and needs to be restarted if you need to connect again.
Pingback: Bash UDP Reverse Shell & other fun things | Separallel
May 3, 2014 at 4:33 pm
Man this is a very useful trick
May 3, 2014 at 7:07 pm
In case your pal have an SSH server (example, remote login enabled on Max OS), you can use the SSH tunnelling part to avoid your pal to configure his box to forward ports, then you can ssh connect on te local forwarded port. This works very well and give a real terminal a lot more easy to use thant a nc connection.
June 5, 2014 at 5:17 pm
Here’s yet another approach to the same problem:
1. On your end (again assuming no firewall) start a netcat instance listening for inbound tcp connections on port 6000 using:
2. The remote machine (the one that you need to be reverse-connect to and execute commands on) runs bash redirecting its standard input output and error to a socket connected to your listening netcat using:
The above uses bash built in /dev/tcp/ which doesn’t exist on the /dev/ filesystem but instead creates a tcp socket.
Similar effect could be achieved using UDP instead of TCP via /dev/udp/… on the client side and “nc -u -l -p 53” on the server. This in case for example that the outbound connections of the client are limited to say DNS only 😉
November 12, 2015 at 8:54 pm
Nice tricks! I’ve learned a couple of things today.
It should be noted that both methods open **huge remote execution holes**, though I believe (correct me if I’m wrong), the original method can be made secure by using “nc -l 127.0.0.1 6000” rather than “nc -l 6000”.
November 15, 2015 at 11:47 am
This won’t work. If you bind “nc” to “127.0.0.1”, it won’t accept remote connections at all. Actually the alternative method suggested by “telbizov” is rather secure — the client connects to your machine and you execute the commands. The worst thing in this case would be that someone else connects before your friend, but you’ll easily notice that.