Socat – ssl-enabled netcat + much moreDuring recent VA testing, I needed an ssl-enabled Netcat to shovel some hand-crafted attacks at a web server.
After looking at and rejecting ncat - too rough around the edges – I turned to socat.
Socat turned out to be a well-honed jewel of a program. This write-up gives a quick overview of features, and also quickly documents install and basic use.
The basic ideaThe program has an elegant design.
The man page says it all:
Socat is a command line based utility that establishes two bidirectional byte streams and transfers data between them. Because the streams can be constructed from a large set of different types of data sinks and sources (see address types), and because lots of address options may be applied to the streams, socat can be used for many different purposes.Conceptually the program works like this:
Figure 1 Socat's Bidirectional Data flow
Specifying the commandThe command syntax is:
socat [options] <address> <address>
where the "address" can be any of:
There are a multitude of options to allow fine-tuning of a given connection.
|CREATE:<filename>||Opens <filename> and uses the file descriptor for writing|
|EXEC:<command-line>||Forks a sub-process, uses exec()|
|SYSTEM:<shell-command>||Forks a sub-process, uses system()|
|FD:<fdnum> (file descriptor)||Uses the Unix file descriptor specified|
|STDERR, STDIN, STDIO, STDOUT||Uses the specified file descriptor|
|GOPEN:<filename>||"Generic open" of a file: Could be a file, or a Unix socket|
|OPEN:<filename>||Just open file but fails if Unix socket specified|
|PIPE:<filename>||Open the named pipe|
|PIPE||Create an unnamed pipe – works as echo since everything written to it automatically reappears as read data|
|UNIX-CONNECT:<filename>||Connects to <filename> assuming it is a UNIX domain socket.|
|UNIX-LISTEN:<filename>||Listens on <filename> using a UNIX domain stream socket and accepts a connection.|
|IP4:<host>:<protocol>||Opens a raw IPv4 socket. If desired, can even send IP hdrs as part of the data|
|IP6:<host>:<protocol>||Idem for IPv6|
|TCP4:<host>:<port>||Idem using Tcp V4|
|TCP4-LISTEN:<port>||Listens on Tcp V4 <port>|
|TCP6:<host>:<port>; TCP6-LISTEN:<port>||Idem using Tcp V6|
|UDP4:<host>:<port>; UDP4-LISTEN:<port>||Idem using Udp V4|
|UDP6:<host>:<port>; UDP6-LISTEN:<port>||Idem using Udp V6|
|OPENSSL:<host>:<port>||Establish an SSL connection|
|OPENSSL-LISTEN:<port>||Listens of tcp4 <port>, behaves as an SSL server|
|PROXY:<proxy>:<hostname>:<port>||Connects to an HTTP proxy server on port 8080, and send a CONNECT request for <hostname> on Tcp v4 <port>|
|PTY||Generates a pseudo-terminal and uses its master side. Another process can open the slave side and use it like a serial port or dumb terminal|
|READLINE||Use GNU readline and history on stdio to allow editing / reusing of input lines|
|SOCKS4:<socks-server>:<host>:<port>||Connects via <socks-server> [IPv4 address] to <host> [IPv4 address] on <port> [TCP service], using socks V4 protocol.|
|SOCKS4A:<socks-server>:<host>:<port>||Idem with socks V4a protocol|
Some examplesThe program distro includes a file with lots of examples. Here are a few:
|socat - TCP:10.1.1.1:80||Similar to "netcat 10.1.1.1 80|
|socat - TCP-LISTEN:25,crlf||Listen on port 25, wait for an incoming connection, use CR+NL on this connection, relay data to and from stdio|
|socat TCP-LISTEN:80,reuseaddr,fork,su=nobody TCP:www.dmz.mydomain.org:80||Reverse proxy TCP port 80 from everywhere (internet, intranet, dmz) through the firewall to the DMZ webserver|
|socat UNIX-LISTEN:/tmp/.X11-unix/X1,fork PROXY:firewall:loopback:6000||Found an XWindow Server on an Http proxy with IP filters but allows Http CONNECT to loopback? …|
So prepare your host: rm -f /tmp/.X11-unix/X1
Then relay a pseudo display :1 on your machine to victim:0
|xterm1$ socat -d -d exec:"ssh target ~/bin/socat -d -d unix-l:/tmp/.X11-unix/X1 -" unix:/tmp/.X11-unix/X0|
xterm2$ ssh target
target$ DISPLAY=:1 myxapplication
|Access local display from ssh server, when ssh port forwarding is disabled|
// socat must be installed on ssh server host
// might have to use xauth...
// this example is one-shot, because ',' cannot be passed to remote socat
|(echo -e "CONNECT 18.104.22.168:80 HTTP/1.0\n"; sleep 5; echo -e "GET /download/file HTTP/1.0\n"; sleep 10) |socat -d -d -t 3600 - tcp:proxy:8080,crlf||Download with proxy CONNECT|
InstallationInstallation is simple. I did my install on a development RHEL5 with OpenSSL and standard development tools installed.
Once I remembered to remount my external USB drive with the EXEC option so that "configure" could execute gcc, then standard gnu install worked fine:
Had to allocate /usr/local/man/man1 for the manpage before installing.
USing socat as ssl-enabled NetcatThis section documents basic use of socat as an ssl-enabled netcat replacement.
Build an input file containing Http headersDid a wireshark trace of an ordinary web site (www.cisco.com) to get some http headers:
GET / HTTP/1.1
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:22.214.171.124) Gecko/2009082505 Red Hat/3.0.14-1.el5_4 Firefox/3.0.14
Web servers want CRLF, so used unix2dos command to do this.
unix2dos http-requestNote the blank line at the end to tell the web server that there are no more headers.
This then became the input file containing http headers to send to the web server.
Specifying the socat cmdOpenSSL will verify the certificate to ensure the CA is known. So need to tell OpenSSL where to find the list of CAs.
The socat cmd is:
socat -ddd -v ./http-request OPENSSL:mail.google.com:443,cafile=/etc/pki/tls/certs/ca-bundle.crt
Note that this will send the whole input file to the server in one operation. Then socat will write the web server's response (in clear text) to the end of the "http-request" file.
Interactive modeAnother possibility is full interactive mode. Each line (i.e. http header) can be edited before sending it along to the web server.
Here is the cmd that can be used:
socat -ddd -v readline,history=http-request OPENSSL:mail.google.com:443,cafile=/etc/pki/tls/certs/ca-bundle.crt
Standard GNU readline / history file support is used, so on my PC, ESC got me to history mode and "up" key moved back through the history file.
The web server's output will be echoed back (in the clear) to STDOUT.
This gives full manual control of all data sent to the web server.
Here is the output: Sample session output