From 8b17dc3472a9c11139d0058bbf8b42eae66022b8 Mon Sep 17 00:00:00 2001 From: jeromemarchand <38073585+jeromemarchand@users.noreply.github.com> Date: Sat, 4 Aug 2018 07:09:36 +0200 Subject: [PATCH] sslsniff: add NSS support (#1908) * sslsniff: add NSS support * sslsniff: update documentation --- man/man8/sslsniff.8 | 18 +++++++++--------- tools/sslsniff.py | 21 +++++++++++++++++++-- tools/sslsniff_example.txt | 16 +++++++++------- 3 files changed, 37 insertions(+), 18 deletions(-) diff --git a/man/man8/sslsniff.8 b/man/man8/sslsniff.8 index e20e28a..72836e2 100644 --- a/man/man8/sslsniff.8 +++ b/man/man8/sslsniff.8 @@ -1,12 +1,12 @@ .TH sslsniff 8 "2016-08-16" "USER COMMANDS" .SH NAME -sslsniff \- Print data passed to OpenSSL. Uses Linux eBPF/bcc. +sslsniff \- Print data passed to OpenSSL, GnuTLS or NSS. Uses Linux eBPF/bcc. .SH SYNOPSIS -.B sslsniff +.B sslsniff [-h] [-p PID] [-c COMM] [-o] [-g] [-n] [-d] .SH DESCRIPTION -sslsniff prints data sent to SSL_write and SSL_read OpenSSL functions, allowing -us to read plain text content before encryption (when writing) and after -decryption (when reading). +sslsniff prints data sent to write/send and read/recv functions of +OpenSSL, GnuTLS and NSS, allowing us to read plain text content before +encryption (when writing) and after decryption (when reading). This works reading the second parameter of both functions (*buf). @@ -15,13 +15,13 @@ Since this uses BPF, only the root user can use this tool. CONFIG_BPF and bcc. .SH EXAMPLES .TP -Print all calls to SSL_write and SSL_read system-wide: +Print all calls to SSL write/send and read/recv system-wide: # .B sslsniff .SH FIELDS .TP FUNC -Which function is being called (SSL_write or SSL_read) +Which function is being called (write/send or read/recv) .TP TIME Time of the command, in seconds. @@ -30,10 +30,10 @@ COMM Entered command. .TP PID -Process ID calling OpenSSL. +Process ID calling SSL. .TP LEN -Bytes written or read by OpenSSL functions. +Bytes written or read by SSL functions. .SH SOURCE This is from bcc. .IP diff --git a/tools/sslsniff.py b/tools/sslsniff.py index 174577b..2e74fba 100755 --- a/tools/sslsniff.py +++ b/tools/sslsniff.py @@ -1,7 +1,7 @@ #!/usr/bin/python # -# sslsniff Captures data on read/recv or write/send functions of OpenSSL and -# GnuTLS +# sslsniff Captures data on read/recv or write/send functions of OpenSSL, +# GnuTLS and NSS # For Linux, uses BCC, eBPF. # # USAGE: sslsniff.py [-h] [-p PID] [-c COMM] [-o] [-g] [-d] @@ -25,6 +25,7 @@ import argparse ./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 """ parser = argparse.ArgumentParser( description="Sniff SSL data", @@ -37,6 +38,8 @@ parser.add_argument("-o", "--no-openssl", action="store_false", dest="openssl", help="do not show OpenSSL calls.") parser.add_argument("-g", "--no-gnutls", action="store_false", dest="gnutls", help="do not show GnuTLS calls.") +parser.add_argument("-n", "--no-nss", action="store_false", dest="nss", + help="do not show NSS calls.") parser.add_argument('-d', '--debug', dest='debug', action='count', default=0, help='debug mode.') parser.add_argument("--ebpf", action="store_true", @@ -149,6 +152,20 @@ b = BPF(text=prog) b.attach_uretprobe(name="gnutls", sym="gnutls_record_recv", fn_name="probe_SSL_read_exit", pid=args.pid or -1) +if args.nss: + b.attach_uprobe(name="nspr4", sym="PR_Write", fn_name="probe_SSL_write", + pid=args.pid or -1) + b.attach_uprobe(name="nspr4", sym="PR_Send", fn_name="probe_SSL_write", + pid=args.pid or -1) + b.attach_uprobe(name="nspr4", sym="PR_Read", fn_name="probe_SSL_read_enter", + pid=args.pid or -1) + b.attach_uretprobe(name="nspr4", sym="PR_Read", + fn_name="probe_SSL_read_exit", pid=args.pid or -1) + b.attach_uprobe(name="nspr4", sym="PR_Recv", fn_name="probe_SSL_read_enter", + pid=args.pid or -1) + b.attach_uretprobe(name="nspr4", sym="PR_Recv", + fn_name="probe_SSL_read_exit", pid=args.pid or -1) + # define output data structure in Python TASK_COMM_LEN = 16 # linux/sched.h MAX_BUF_SIZE = 464 # Limited by the BPF stack diff --git a/tools/sslsniff_example.txt b/tools/sslsniff_example.txt index c16b572..8c51722 100644 --- a/tools/sslsniff_example.txt +++ b/tools/sslsniff_example.txt @@ -1,16 +1,16 @@ Demonstrations of sslsniff.py -This tool traces the OpenSSL functions SSL_READ and SSL_WRITE. -Data passed to this functions is printed as plain text. -Useful, for example, to sniff HTTP before encrypted with SSL. +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 -SSL_WRITE 0.000000000 curl 12915 75 +WRITE/SEND 0.000000000 curl 12915 75 ----- DATA ----- GET / HTTP/1.1 Host: example.com @@ -20,7 +20,7 @@ Accept: */* ----- END DATA ----- -SSL_READ 0.127144585 curl 12915 333 +READ/RECV 0.127144585 curl 12915 333 ----- DATA ----- HTTP/1.1 200 OK Cache-Control: max-age=604800 @@ -38,7 +38,7 @@ Content-Length: 1270 ----- END DATA ----- -SSL_READ 0.129967972 curl 12915 1270 +READ/RECV 0.129967972 curl 12915 1270 ----- DATA ----- @@ -65,7 +65,7 @@ SSL_READ 0.129967972 curl 12915 1270 USAGE message: -usage: sslsniff.py [-h] [-p PID] [-c COMM] [-o] [-g] [-d] +usage: sslsniff.py [-h] [-p PID] [-c COMM] [-o] [-g] [-n] [-d] Sniff SSL data @@ -75,6 +75,7 @@ Sniff SSL data -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. examples: @@ -83,3 +84,4 @@ Sniff SSL data ./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 -- 2.17.1