Blob Blame History Raw
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 -----
 <!doctype html>
 <html>
@@ -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