2009-11-09

Socat

Socat – ssl-enabled netcat + much more

During 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 idea

The 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 command

The command syntax is:

socat [options] <address> <address>

where the "address" can be any of:

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
There are a multitude of options to allow fine-tuning of a given connection.

Some examples

The 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 128.129.130.131: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

Installation

Installation 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:

./configure
make
make install

Had to allocate /usr/local/man/man1 for the manpage before installing.

USing socat as ssl-enabled Netcat

This section documents basic use of socat as an ssl-enabled netcat replacement.

Build an input file containing Http headers

Did 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:1.9.0.14) Gecko/2009082505 Red Hat/3.0.14-1.el5_4 Firefox/3.0.14

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

Accept-Language: en-us,en;q=0.5

Accept-Encoding: gzip,deflate

Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7

Keep-Alive: 300

Connection: keep-alive



Web servers want CRLF, so used unix2dos command to do this.

unix2dos http-request

Note 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 cmd

OpenSSL 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 mode

Another 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

3 comments:

jhony said...

Was looking for more information for socat for one of my projects and your guide helped me alot! its written well and good instructions

JeCksOn said...

I was doing a project with my friend when we came across this site. My friend is a computer studies student she founf your post really helpful. Keep sharing. Thanks.

Jake K said...

Thank you for sharing this