From 6a906a626728da97e4568d2df958c62d04804c37 Mon Sep 17 00:00:00 2001 From: Hubert Kario Date: Fri, 16 Sep 2016 23:06:34 +0200 Subject: [PATCH] add support for collecting supported NPN protocols --- cipherscan | 42 +++++++++++++++++++++++++++++------------- top1m/parse_results.py | 18 ++++++++++++++++++ 2 files changed, 47 insertions(+), 13 deletions(-) diff --git a/cipherscan b/cipherscan index 9040cc6..5f79abd 100755 --- a/cipherscan +++ b/cipherscan @@ -377,6 +377,7 @@ parse_openssl_output() { current_sigalg="None" current_renegotiation="False" current_compression="" + current_npn="None" certs_found=0 current_raw_certificates=() @@ -399,6 +400,12 @@ parse_openssl_output() { continue fi + # get NPN protocols + if [[ $line =~ Protocols\ advertised\ by\ server:\ (.*) ]]; then + current_npn="${BASH_REMATCH[1]// /}" + continue + fi + # extract selected cipher if [[ $line =~ New,\ ]]; then local match=($line) @@ -620,6 +627,7 @@ test_cipher_on_target() { trusted=$current_trusted tickethint=$current_tickethint ocspstaple=$current_ocspstaple + npn="$current_npn" certificates="$current_certificates" # grab the cipher and PFS key size done @@ -632,7 +640,7 @@ test_cipher_on_target() { # if cipher contains NONE, the cipher wasn't accepted elif [[ "$cipher" == '(NONE) ' ]]; then - result="$cipher $protocols $pubkey $sigalg $trusted $tickethint $ocspstaple $pfs $current_curves $curves_ordering" + result="$cipher $protocols $pubkey $sigalg $trusted $tickethint $ocspstaple $npn $pfs $current_curves $curves_ordering" verbose "handshake failed, server returned ciphersuite '$result'" return 1 @@ -653,7 +661,7 @@ test_cipher_on_target() { current_curves="$(get_curve_name "$(echo $pfs|cut -d ',' -f2)")" fi fi - result="$cipher $protocols $pubkey $sigalg $trusted $tickethint $ocspstaple $pfs $current_curves $curves_ordering" + result="$cipher $protocols $pubkey $sigalg $trusted $tickethint $ocspstaple $npn $pfs $current_curves $curves_ordering" verbose "handshake succeeded, server returned ciphersuite '$result'" return 0 fi @@ -693,7 +701,7 @@ get_cipher_pref() { sslcommand+=" -CAfile $CACERTS" fi sslcommand+=" -trusted_first -status $SCLIENTARGS -connect $TARGET" - sslcommand+=" -cipher $ciphersuite" + sslcommand+=" -cipher $ciphersuite -nextprotoneg http/1.1" verbose "Connecting to '$TARGET' with ciphersuite '$ciphersuite'" # If the connection succeeded with the current cipher, benchmark and store @@ -728,6 +736,7 @@ display_results_in_terminal() { local sigalg local trusted local tickethint + local npn local ocspstaple local curvesordering local different=False @@ -771,8 +780,9 @@ display_results_in_terminal() { trusted="${cipher_data[4]}" tickethint="${cipher_data[5]}" ocspstaple="${cipher_data[6]}" - if [[ $TEST_CURVES == "True" && -n ${cipher_data[9]} ]]; then - curvesordering="${cipher_data[9]}" + npn="${cipher_data[7]}" + if [[ $TEST_CURVES == "True" && -n ${cipher_data[10]} ]]; then + curvesordering="${cipher_data[10]}" fi else if [[ "$pubkey" != "${cipher_data[2]}" ]]; then @@ -790,10 +800,14 @@ display_results_in_terminal() { if [[ "$ocspstaple" != "${cipher_data[6]}" ]]; then different=True fi - if [[ -z $curvesordering && -n "${cipher_data[9]}" ]]; then - curvesordering="${cipher_data[9]}" + if [[ "$npn" != "${cipher_data[7]}" ]]; then + different=True fi - if [[ -n $curvesordering && "$curvesordering" != "${cipher_data[9]}" ]]; then + if [[ -z $curvesordering && -n "${cipher_data[10]}" ]]; then + curvesordering="${cipher_data[10]}" + fi + if [[ -n $curvesordering && "$curvesordering" != "${cipher_data[10]}" ]]; then + echo "CURVESORDERING" different=True fi fi @@ -803,7 +817,7 @@ display_results_in_terminal() { header="prio ciphersuite protocols" if [[ $different == "True" ]]; then - header+=" pubkey_size signature_algoritm trusted ticket_hint ocsp_staple" + header+=" pubkey_size signature_algoritm trusted ticket_hint ocsp_staple npn" fi header+=" pfs" if [[ $has_curves == "True" ]]; then @@ -825,7 +839,7 @@ display_results_in_terminal() { echo "$result"|grep -v '(NONE)' else # prints priority, ciphersuite, protocols and pfs - awk '!/(NONE)/{print $1 " " $2 " " $3 " " $9 " " $10}' <<<"$result" + awk '!/(NONE)/{print $1 " " $2 " " $3 " " $10 " " $11}' <<<"$result" fi done|column -t echo @@ -848,6 +862,7 @@ display_results_in_terminal() { if [[ $different != "True" ]]; then echo -e "Certificate: $trusted, $pubkey bits, $sigalg signature" echo "TLS ticket lifetime hint: $tickethint" + echo "NPN protocols: $npn" fi if [[ $ocspstaple == "True" ]]; then echo -e "OCSP stapling: ${c_green}supported${c_reset}" @@ -984,15 +999,16 @@ display_results_in_json() { fi echo -n "\"ticket_hint\":\"${cipher_arr[5]}\"," echo -n "\"ocsp_stapling\":\"${cipher_arr[6]}\"," - pfs="${cipher_arr[7]}" + echo -n "\"npn\":[\"${cipher_arr[7]//,/\",\"}\"]," + pfs="${cipher_arr[8]}" [[ -z $pfs ]] && pfs="None" echo -n "\"pfs\":\"$pfs\"" if [[ "${cipher_arr[0]}" =~ ECDH ]]; then echo -n "," - echo -n "\"curves\":[\"${cipher_arr[8]//,/\",\"}\"]" + echo -n "\"curves\":[\"${cipher_arr[9]//,/\",\"}\"]" if [[ $TEST_CURVES == "True" ]]; then echo -n "," - echo -n "\"curves_ordering\":\"${cipher_arr[9]}\"" + echo -n "\"curves_ordering\":\"${cipher_arr[10]}\"" fi fi echo -n "}" diff --git a/top1m/parse_results.py b/top1m/parse_results.py index f163a88..b48cb19 100644 --- a/top1m/parse_results.py +++ b/top1m/parse_results.py @@ -111,6 +111,7 @@ tickethint = defaultdict(int) eccfallback = defaultdict(int) eccordering = defaultdict(int) ecccurve = defaultdict(int) +npn = defaultdict(int) ocspstaple = defaultdict(int) fallbacks = defaultdict(int) # array with indexes of fallback names for the matrix report @@ -174,6 +175,7 @@ for r,d,flist in os.walk(path): tempeccfallback = "unknown" tempeccordering = "unknown" tempecccurve = {} + tempnpn = {} tempfallbacks = {} """ supported ciphers by the server under scan """ tempcipherstats = {} @@ -500,6 +502,13 @@ for r,d,flist in os.walk(path): elif protocol == 'TLSv1.2': TLS1_2 = True + # save NPN protocols supported + if 'npn' in entry: + for proto in entry['npn']: + tempnpn[proto] = 1 + if len(entry['npn']) == 1: + tempnpn[proto + ' Only'] = 1 + """ save ECC curves stats """ if 'curves_ordering' in entry: tempeccordering = entry['curves_ordering'] @@ -593,6 +602,9 @@ for r,d,flist in os.walk(path): for s in tempecccurve: ecccurve[s] += 1 + for s in tempnpn: + npn[s] += 1 + if ocsp_stapling is None: ocspstaple['Unknown'] += 1 elif ocsp_stapling: @@ -796,6 +808,12 @@ for stat in sorted(handshakestats): percent = round(handshakestats[stat] / total * 100, 4) sys.stdout.write(stat.ljust(25) + " " + str(handshakestats[stat]).ljust(10) + str(percent).ljust(4) + "\n") +print("\nSupported NPN protocols Count Percent ") +print("-------------------------+---------+--------") +for name, val in sorted(npn.items()): + percent = round(val / total * 100, 4) + sys.stdout.write(name.ljust(25) + " " + str(val).ljust(10) + str(percent).ljust(9) + "\n") + print("\nSupported PFS Count Percent PFS Percent") print("-------------------------+---------+--------+-----------") for stat in sorted(pfsstats):