Getting SSH via cron job with Reverse Remote Shell
by Dust Storm on Feb.22, 2011, under Networking
I have been developing some web applications for a friend for some time and I finally got to a point where I needed an SSH shell to test some scripts I wrote in Python. Up until recently, I had been using FTP to upload my PHP files and then just browse to the protected page to test the functionality. The hosting provider only offers FTP to upload files and has SSH disabled to my friend. While I have FTP access to his server, the only thing I could use was cron jobs that could only run as often as 15 minutes. While I could wait that long to see if everything runs smoothly, fixing one set of errors and waiting 15 minutes for the next would be a little ridiculous. The rest of this post is how I ended up getting SSH on the remote server with a little program called Reverse Remote SSH (RRS).
Initial Attempts
Starting SSH with listener loopback
My search began with Google, throwing in terms like ‘remote ssh’, ‘cron ssh’, etc., and after a good 20 minutes of searching and reading, I found a couple of things that might work. The first web page I found explained a way to run SSH in such a way that would connect from the remote host to the localhost and open a listening tunnel. I use the following command to create a direct tunnel to my local computer: ssh -R 2210:localhost:22 example.dyndns.com. The -R switch sets up SSH as a listener on the remote server on localhost:22 and connects to example.dyndns.com on port 2210. On the client end, the user would use SSH to connect to the localhost on port 2210 once the cron job has run and created the tunnel. After spending about 20 minutes finding this, it turns out that my friend does not have permission to run SSH on his server, making this option a dead end.
Using Netcat to start a shell on connection
At this point, my roommate (website) steps in and mentions a project that sets up SSH automatically, but unfortunately the link to the download on the project site was broken. Further searches for the compressed libraries yielded more sites that linked the same broken file. He did find a site that uses netcat to start SSH and connect to a remote host. According to the website, netcat is set up on the local machine to listen for an incoming connection and the verbose flag is set so the user will know when the connection has been made. On the remote server, netcat connects to the local machine and starts a new shell that can be accessed by the local machine. Thankfully, netcat was not blocked on the system and I was able to run commands on the remote server, although unencrypted.
Reverse Remote Shell
Finding the project files
Although I had netcat working and I could run commands, I was still missing the shell prompt and the secure connection between me and the server. I continued searching for the files until I got lucky and found a mirrored copy on Packet Storm. I had to use 7zip on Windows to extract the files since the archive manager on Ubuntu was unable to read the compressed files. I think it has something to do with the packaging function in the makefile, but I have uploaded a fixed copy.
Compiling the Source
With the extracted files on my Ubuntu machine, I proceed to run make since there is no configure file. Typically, make does some pre-processing before running make install, but for this package, I was presented with a usage screen and multiple options along with short descriptions of which one to use depending on the environment it would be built in. In my situation, I’m building for a generic Linux OS (Desktop: Ubuntu, Server: CentOS). Running the command make generic initially returns an error saying that it can’t find the SSL libraries. After grabbing the SSL development libraries from the Ubuntu repositories, I ran the make again with lots of warnings, but it ran successfully. In the final step of compiling the source, I add the PREFIX gcc variable to build the executable to a custom directory: make install PREFIX=$HOME/rrs. The install made a binary file and a man page in the custom directory.
Getting RRS to run
After uploading the files, I was hoping that the compilation I did on my machine would work on the remote server. Thankfully it did, but another problem presented itself: missing libraries. The cron job output only listed one missing library, so I figured I’d just find the library on my Ubuntu box and throw it in a directory on the server. I had to modify the cron job to add the custom directory to the libraries system path variable so it would run. My final cron job loos like this: LD_LIBRARY_PATH=path/lib path/rrs -l -p 3333 where path/lib is where I put the library and path/rrs is where the executable resides. So I wait 15 minutes after the last cron job run to see if the library I copied over worked, and it did, only with another missing library. At this point, I figured that there were going to be a number of other libraries missing, so I start my run and wait. It turns out that there were only three libraries missing: libc, libcrypto, and libssl. Once I got all the libraries up, I noticed that the cron job didn’t generate any output, so I tired to connect with SSH on my local machine, with much success. I was able to connect like via SSH and get a shell with a prompt. After customizing the prompt, I was all set to go.
No static compile
For those who compile code manually more often than I do, there’s a flag you can pass to gcc that will make a static executable with the dependencies and required libraries compiled into the executable. For some reason, the way the developer made this program prevents the static flag from being used and causes an error during compilation. Make returns errors that the SSL associated libraries cannot be found. I haven’t looked into why I can’t find them, but my guess is that it’s looking for a local copy of the development libraries instead of using the system variable to find them during static compilation. With that said, being able to use my own Ubuntu libraries is good enough for me.
Conclusions
First off, as my roommate has observed, why give the people the ability to run cron jobs and not shell access? I guess the 15 minute minimum job repeat will deter hogging system resources, but it still leaves open the ability to run programs, and in this situation, run something that will bet me SSH. Secondly, I could have stopped when I got netcat working with an unsecured shell, but I missed having the prompt with the directory of where I am. Lastly, RRS works just like the name suggests. I didn’t have to create any certificates or keys to use when I threw it up on the remote host, but I was able to get it to generate keys and certificates on my machine just in-case. There are probably other libraries that RRS relies on to run, but the three I listed were only the ones that were missing and I’m pretty sure other systems that are built as web servers would be very similar. And I didn’t have to cross compile.