Demonstrations of sslsniff.py


This tool traces the write/send and read/recv functions of OpenSSL,
GnuTLS and NSS.  Data passed to this functions is printed as plain
text.  Useful, for example, to sniff HTTP before encrypted with SSL.


Output of tool executing in other shell "curl https://example.com"

% sudo python sslsniff.py
FUNC         TIME(s)            COMM             PID    LEN
WRITE/SEND   0.000000000        curl             12915  75
----- DATA -----
GET / HTTP/1.1
Host: example.com
User-Agent: curl/7.50.1
Accept: */*


----- END DATA -----

READ/RECV    0.127144585        curl             12915  333
----- DATA -----
HTTP/1.1 200 OK
Cache-Control: max-age=604800
Content-Type: text/html
Date: Tue, 16 Aug 2016 15:42:12 GMT
Etag: "359670651+gzip+ident"
Expires: Tue, 23 Aug 2016 15:42:12 GMT
Last-Modified: Fri, 09 Aug 2013 23:54:35 GMT
Server: ECS (iad/18CB)
Vary: Accept-Encoding
X-Cache: HIT
x-ec-custom-error: 1
Content-Length: 1270


----- END DATA -----

READ/RECV    0.129967972        curl             12915  1270
----- DATA -----
<!doctype html>
<html>
<head>
    <title>Example Domain</title>

    <meta charset="utf-8" />
    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <style type="text/css">
    body {
        background-color: #f0f0f2;
        margin: 0;
        padding: 0;
        font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;

    }
    div {
        w
----- END DATA (TRUNCATED, 798 bytes lost) -----

Using the --hexdump option you will get the exact same output, only the lines
between DATA and END DATA will differ. Those will be replaced with a 16 byte
(32 characters) wide hex-dump, an example of a block of output from sslsniff
called with that option is

READ/RECV    7.405609173        curl             201942 1256
----- DATA -----
3c21646f63747970652068746d6c3e0a
3c68746d6c3e0a3c686561643e0a2020
20203c7469746c653e4578616d706c65
20446f6d61696e3c2f7469746c653e0a
0a202020203c6d657461206368617273
65743d227574662d3822202f3e0a2020
20203c6d65746120687474702d657175
69763d22436f6e74656e742d74797065
2220636f6e74656e743d22746578742f
68746d6c3b20636861727365743d7574
662d3822202f3e0a202020203c6d6574
61206e616d653d2276696577706f7274
2220636f6e74656e743d227769647468
3d6465766963652d77696474682c2069
6e697469616c2d7363616c653d312220
2f3e0a202020203c7374796c65207479
70653d22746578742f637373223e0a20
202020626f6479207b0a202020202020
20206261636b67726f756e642d636f6c
6f723a20236630663066323b0a202020
20202020206d617267696e3a20303b0a
202020202020202070616464696e673a
20303b0a2020202020202020666f6e74
2d66616d696c793a202d6170706c652d
73797374656d2c2073797374656d2d75
692c20426c696e6b4d61635379737465
6d466f6e742c20225365676f65205549
222c20224f70656e2053616e73222c20
2248656c766574696361204e65756522
----- END DATA (TRUNCATED, 792 bytes lost) -----

This is useful to sniff binary protocols where the UTF-8 decode might insert a
lot of characters that are not printable or even Unicode replacement
characters.


Use -l or --latency option to show function latency, and show handshake latency
by using both -l and --handshake. This is useful for SSL/TLS performance
analysis. Tracing output of "echo | openssl s_client -connect example.com:443":

# ./sslsniff.py -l --handshake
FUNC         TIME(s)            COMM             PID     LEN    LAT(ms)
WRITE/SEND   0.000000000        openssl          10377   1      0.005
----- DATA -----


----- END DATA -----

Trace localhost server instead of example.com. It takes 0.7ms for server
handshake before secure connection is ready for initial SSL_read or SSL_write.

# ./sslsniff.py -l --handshake
FUNC         TIME(s)            COMM             PID     LEN    LAT(ms)
HANDSHAKE    0.000000000        nginx            7081    0      0.699
WRITE/SEND   0.000132180        openssl          14800   1      0.010
----- DATA -----


----- END DATA -----

READ/RECV    0.000136583        nginx            7081    1      0.004
----- DATA -----


----- END DATA -----

Tracing output of "echo | gnutls-cli -p 443 example.com":

# ./sslsniff.py -l --handshake
FUNC         TIME(s)            COMM             PID     LEN    LAT(ms)
WRITE/SEND   0.000000000        gnutls-cli       43554   1      0.012
----- DATA -----


----- END DATA -----

Tracing output of "echo | gnutls-cli -p 443 --insecure localhost":

# ./sslsniff.py -l --handshake
FUNC         TIME(s)            COMM             PID     LEN    LAT(ms)
HANDSHAKE    0.000000000        nginx            7081    0      0.710
WRITE/SEND   0.000045126        gnutls-cli       43752   1      0.014
----- DATA -----


----- END DATA -----

READ/RECV    0.000049464        nginx            7081    1      0.004
----- DATA -----


----- END DATA -----

Tracing few extra libraries (useful for docker containers and other isolated
apps)

# ./sslsniff.py --extra-lib openssl:/var/lib/docker/overlay2/l/S4EMHE/lib/libssl.so.1.1



USAGE message:

usage: sslsniff.py [-h] [-p PID] [-u UID] [-x] [-c COMM] [-o] [-g] [-n] [-d]
                   [--hexdump] [--max-buffer-size MAX_BUFFER_SIZE] [-l]
                   [--handshake] [--extra-lib EXTRA_LIB]

Sniff SSL data

optional arguments:
  -h, --help            show this help message and exit
  -p PID, --pid PID     sniff this PID only.
  -u UID, --uid UID     sniff this UID only.
  -x, --extra           show extra fields (UID, TID)
  -c COMM, --comm COMM  sniff only commands matching string.
  -o, --no-openssl      do not show OpenSSL calls.
  -g, --no-gnutls       do not show GnuTLS calls.
  -n, --no-nss          do not show NSS calls.
  -d, --debug           debug mode.
  --hexdump             show data as hexdump instead of trying to decode it as
                        UTF-8
  --max-buffer-size MAX_BUFFER_SIZE
                        Size of captured buffer
  -l, --latency         show function latency
  --handshake           show SSL handshake latency, enabled only if latency
                        option is on. 
  --extra-lib EXTRA_LIB
                        Intercept calls from extra library
                        (format: lib_type:lib_path)



examples:
    ./sslsniff              # sniff OpenSSL and GnuTLS functions
    ./sslsniff -p 181       # sniff PID 181 only
    ./sslsniff -u 1000      # sniff only UID 1000
    ./sslsniff -c curl      # sniff curl command only
    ./sslsniff --no-openssl # don't show OpenSSL calls
    ./sslsniff --no-gnutls  # don't show GnuTLS calls
    ./sslsniff --no-nss     # don't show NSS calls
    ./sslsniff --hexdump    # show data as hex instead of trying to decode it as UTF-8
    ./sslsniff -x           # show process UID and TID
    ./sslsniff -l           # show function latency
    ./sslsniff -l --handshake  # show SSL handshake latency
    ./sslsniff --extra-lib openssl:/path/libssl.so.1.1 # sniff extra library
