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