From 6ab5701ad023aeaa2d1d2d86902febb1f6fae7b8 Mon Sep 17 00:00:00 2001 From: Johanna Amann Date: Mon, 9 Mar 2015 12:33:56 -0700 Subject: [PATCH 1/3] Update certificate validation script - new version will cache valid intermediate chains that it encounters on the wire and use those to try to validate chains that might be missing intermediate certificates. This vastly improves the number of certificates that Bro can validate. The only drawback is that now validation behavior is not entirely predictable anymore - the certificate of a server can fail to validate when Bro just started up (due to the intermediate missing), and succeed later, when the intermediate can be found in the cache. Has been tested on big-ish clusters and should not introduce any performance problems. --- .../policy/protocols/ssl/validate-certs.bro | 129 +++++++++++++++--- .../ssl.log | 15 ++ .../ssl-all.log | 23 ++++ .../ssl.log | 11 -- .../Traces/tls/missing-intermediate.pcap | Bin 0 -> 13449 bytes .../protocols/ssl/validate-certs-cluster.bro | 37 +++++ .../policy/protocols/ssl/validate-certs.bro | 7 +- 7 files changed, 191 insertions(+), 31 deletions(-) create mode 100644 testing/btest/Baseline/scripts.policy.protocols.ssl.validate-certs-cluster/ssl.log create mode 100644 testing/btest/Baseline/scripts.policy.protocols.ssl.validate-certs/ssl-all.log delete mode 100644 testing/btest/Baseline/scripts.policy.protocols.ssl.validate-certs/ssl.log create mode 100644 testing/btest/Traces/tls/missing-intermediate.pcap create mode 100644 testing/btest/scripts/policy/protocols/ssl/validate-certs-cluster.bro diff --git a/scripts/policy/protocols/ssl/validate-certs.bro b/scripts/policy/protocols/ssl/validate-certs.bro index 19b0b70806..d2b3befaed 100644 --- a/scripts/policy/protocols/ssl/validate-certs.bro +++ b/scripts/policy/protocols/ssl/validate-certs.bro @@ -1,4 +1,6 @@ ##! Perform full certificate chain validation for SSL certificates. +# Also caches all intermediate certificates encountered so far and use them +# for future validations. @load base/frameworks/notice @load base/protocols/ssl @@ -19,12 +21,92 @@ export { }; ## MD5 hash values for recently validated chains along with the - ## validation status message are kept in this table to avoid constant + ## validation status are kept in this table to avoid constant ## validation every time the same certificate chain is seen. global recently_validated_certs: table[string] of string = table() - &read_expire=5mins &synchronized &redef; + &read_expire=5mins &redef; + + ## Event from a worker to the manager that it has encountered a new + ## valid intermediate + global intermediate_add: event(key: string, value: vector of opaque of x509); + + ## Event from the manager to the workers that a new intermediate chain + ## is to be added + global new_intermediate: event(key: string, value: vector of opaque of x509); } +global intermediate_cache: table[string] of vector of opaque of x509; + +@if ( Cluster::is_enabled() ) +@load base/frameworks/cluster +redef Cluster::manager2worker_events += /SSL::intermediate_add/; +redef Cluster::worker2manager_events += /SSL::new_intermediate/; +@endif + + +function add_to_cache(key: string, value: vector of opaque of x509) + { + intermediate_cache[key] = value; +@if ( Cluster::is_enabled() ) + event SSL::new_intermediate(key, value); +@endif + } + +@if ( Cluster::is_enabled() && Cluster::local_node_type() != Cluster::MANAGER ) +event SSL::intermediate_add(key: string, value: vector of opaque of x509) + { + intermediate_cache[key] = value; + } +@endif + +@if ( Cluster::is_enabled() && Cluster::local_node_type() == Cluster::MANAGER ) +event SSL::new_intermediate(key: string, value: vector of opaque of x509) + { + if ( key in intermediate_cache ) + return; + + intermediate_cache[key] = value; + event SSL::intermediate_add(key, value); + } +@endif + +function cache_validate(chain: vector of opaque of x509): string + { + local chain_hash: vector of string = vector(); + + for ( i in chain ) + chain_hash[i] = sha1_hash(x509_get_certificate_string(chain[i])); + + local chain_id = join_string_vec(chain_hash, "."); + + # If we tried this certificate recently, just return the cached result. + if ( chain_id in recently_validated_certs ) + return recently_validated_certs[chain_id]; + + local result = x509_verify(chain, root_certs); + recently_validated_certs[chain_id] = result$result_string; + + # if we have a working chain where we did not store the intermediate certs + # in our cache yet - do so + if ( result$result_string == "ok" && result?$chain_certs && |result$chain_certs| > 2 ) + { + local result_chain = result$chain_certs; + local icert = x509_parse(result_chain[1]); + if ( icert$subject !in intermediate_cache ) + { + local cachechain: vector of opaque of x509; + for ( i in result_chain ) + { + if ( i >=1 && i<=|result_chain|-2 ) + cachechain[i-1] = result_chain[i]; + } + add_to_cache(icert$subject, cachechain); + } + } + + return result$result_string; + } + event ssl_established(c: connection) &priority=3 { # If there aren't any certs we can't very well do certificate validation. @@ -32,9 +114,30 @@ event ssl_established(c: connection) &priority=3 ! c$ssl$cert_chain[0]?$x509 ) return; - local chain_id = join_string_vec(c$ssl$cert_chain_fuids, "."); - local hash = c$ssl$cert_chain[0]$sha1; + local intermediate_chain: vector of opaque of x509 = vector(); + local issuer = c$ssl$cert_chain[0]$x509$certificate$issuer; + local result: string; + # look if we already have a working chain for the issuer of this cert. + # If yes, try this chain first instead of using the chain supplied from + # the server. + if ( issuer in intermediate_cache ) + { + intermediate_chain[0] = c$ssl$cert_chain[0]$x509$handle; + for ( i in intermediate_cache[issuer] ) + intermediate_chain[i+1] = intermediate_cache[issuer][i]; + + result = cache_validate(intermediate_chain); + if ( result == "ok" ) + { + c$ssl$validation_status = result; + return; + } + } + + # validation with known chains failed or there was no fitting intermediate + # in our store. + # Fall back to validating the certificate with the server-supplied chain local chain: vector of opaque of x509 = vector(); for ( i in c$ssl$cert_chain ) { @@ -42,24 +145,14 @@ event ssl_established(c: connection) &priority=3 chain[i] = c$ssl$cert_chain[i]$x509$handle; } - if ( chain_id in recently_validated_certs ) - { - c$ssl$validation_status = recently_validated_certs[chain_id]; - } - else - { - local result = x509_verify(chain, root_certs); - c$ssl$validation_status = result$result_string; - recently_validated_certs[chain_id] = result$result_string; - } + result = cache_validate(chain); + c$ssl$validation_status = result; - if ( c$ssl$validation_status != "ok" ) + if ( result != "ok" ) { local message = fmt("SSL certificate validation failed with (%s)", c$ssl$validation_status); NOTICE([$note=Invalid_Server_Cert, $msg=message, $sub=c$ssl$subject, $conn=c, - $identifier=cat(c$id$resp_h,c$id$resp_p,hash,c$ssl$validation_status)]); + $identifier=cat(c$id$resp_h,c$id$resp_p,c$ssl$validation_status)]); } } - - diff --git a/testing/btest/Baseline/scripts.policy.protocols.ssl.validate-certs-cluster/ssl.log b/testing/btest/Baseline/scripts.policy.protocols.ssl.validate-certs-cluster/ssl.log new file mode 100644 index 0000000000..df2cdf9732 --- /dev/null +++ b/testing/btest/Baseline/scripts.policy.protocols.ssl.validate-certs-cluster/ssl.log @@ -0,0 +1,15 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path ssl +#open 2015-03-09-19-32-44 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p version cipher curve server_name resumed last_alert next_protocol established cert_chain_fuids client_cert_chain_fuids subject issuer client_subject client_issuer validation_status +#types time string addr port addr port string string string string bool string string bool vector[string] vector[string] string string string string string +1425929564.247511 CXWv6p3arKYeMETxOg 192.168.4.149 58529 128.32.169.140 443 TLSv10 TLS_RSA_WITH_RC4_128_MD5 - - F - - T FTzCuuqU5y7w85H89 (empty) CN=www.cviis.org,OU=Domain Control Validated CN=Starfield Secure Certificate Authority - G2,OU=http://certs.starfieldtech.com/repository/,O=Starfield Technologies\, Inc.,L=Scottsdale,ST=Arizona,C=US - - unable to get local issuer certificate +1425929565.270104 CXWv6p3arKYeMETxOg 192.168.4.149 58529 128.32.169.140 443 TLSv10 TLS_RSA_WITH_RC4_128_MD5 - - F - - T FXzQOu1ZSKSF7H8Ez6 (empty) CN=www.cviis.org,OU=Domain Control Validated CN=Starfield Secure Certificate Authority - G2,OU=http://certs.starfieldtech.com/repository/,O=Starfield Technologies\, Inc.,L=Scottsdale,ST=Arizona,C=US - - unable to get local issuer certificate +1425929566.843026 CjhGID4nQcgTWjvg4c 192.168.4.149 58530 72.167.102.91 443 TLSv12 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 secp256r1 - F - - T F5l2dVkZHiwiOWR67,Fkw2ETDXfIXIvatba,Fbgf8A3V6m8v33wTcj (empty) CN=valid.sfig2.catest.starfieldtech.com,O=Starfield Technologies\, LLC,L=Scottsdale,ST=Arizona,C=US,serialNumber=R-1724741-6,businessCategory=Private Organization,jurisdictionST=Arizona,jurisdictionC=US CN=Starfield Secure Certificate Authority - G2,OU=http://certs.starfieldtech.com/repository/,O=Starfield Technologies\, Inc.,L=Scottsdale,ST=Arizona,C=US - - ok +1425929571.372511 CCvvfg3TEfuqmmG4bh 192.168.4.149 58532 128.32.169.140 443 TLSv10 TLS_RSA_WITH_RC4_128_MD5 - - F - - T FhEtvg4pQ90832J56f (empty) CN=www.cviis.org,OU=Domain Control Validated CN=Starfield Secure Certificate Authority - G2,OU=http://certs.starfieldtech.com/repository/,O=Starfield Technologies\, Inc.,L=Scottsdale,ST=Arizona,C=US - - ok +1425929567.865619 CjhGID4nQcgTWjvg4c 192.168.4.149 58530 72.167.102.91 443 TLSv12 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 secp256r1 - F - - T Fyc6cQ2rMCAhpIGcM5,FoJ8j735m9ogDYopYj,FHaYhA3ykzVlKPnnsc (empty) CN=valid.sfig2.catest.starfieldtech.com,O=Starfield Technologies\, LLC,L=Scottsdale,ST=Arizona,C=US,serialNumber=R-1724741-6,businessCategory=Private Organization,jurisdictionST=Arizona,jurisdictionC=US CN=Starfield Secure Certificate Authority - G2,OU=http://certs.starfieldtech.com/repository/,O=Starfield Technologies\, Inc.,L=Scottsdale,ST=Arizona,C=US - - ok +1425929572.395104 CCvvfg3TEfuqmmG4bh 192.168.4.149 58532 128.32.169.140 443 TLSv10 TLS_RSA_WITH_RC4_128_MD5 - - F - - T FwZZ8034tgyXSponwg (empty) CN=www.cviis.org,OU=Domain Control Validated CN=Starfield Secure Certificate Authority - G2,OU=http://certs.starfieldtech.com/repository/,O=Starfield Technologies\, Inc.,L=Scottsdale,ST=Arizona,C=US - - ok +#close 2015-03-09-19-32-53 diff --git a/testing/btest/Baseline/scripts.policy.protocols.ssl.validate-certs/ssl-all.log b/testing/btest/Baseline/scripts.policy.protocols.ssl.validate-certs/ssl-all.log new file mode 100644 index 0000000000..77ba9233ae --- /dev/null +++ b/testing/btest/Baseline/scripts.policy.protocols.ssl.validate-certs/ssl-all.log @@ -0,0 +1,23 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path ssl +#open 2015-03-09-19-44-42 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p version cipher curve server_name resumed last_alert next_protocol established cert_chain_fuids client_cert_chain_fuids subject issuer client_subject client_issuer validation_status +#types time string addr port addr port string string string string bool string string bool vector[string] vector[string] string string string string string +1394745602.951961 CXWv6p3arKYeMETxOg 192.168.4.149 60539 87.98.220.10 443 TLSv10 TLS_DHE_RSA_WITH_AES_256_CBC_SHA - - F - - T F1fX1R2cDOzbvg17ye,FqPEQR2eytAQybroyl (empty) CN=www.spidh.org,OU=COMODO SSL,OU=Domain Control Validated CN=COMODO SSL CA,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB - - certificate has expired +1394745618.791420 CjhGID4nQcgTWjvg4c 192.168.4.149 60540 122.1.240.204 443 TLSv10 TLS_RSA_WITH_AES_256_CBC_SHA - - F - - T F6NAbK127LhNBaEe5c,FDhmPt28vyXlGMTxP7,F0ROCKibhE1KntJ1h (empty) CN=www.tobu-estate.com,OU=Terms of use at www.verisign.com/rpa (c)05,O=TOBU RAILWAY Co.\,Ltd.,L=Sumida-ku,ST=Tokyo,C=JP CN=VeriSign Class 3 Secure Server CA - G3,OU=Terms of use at https://www.verisign.com/rpa (c)10,OU=VeriSign Trust Network,O=VeriSign\, Inc.,C=US - - ok +#close 2015-03-09-19-44-42 +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path ssl +#open 2015-03-09-19-44-42 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p version cipher curve server_name resumed last_alert next_protocol established cert_chain_fuids client_cert_chain_fuids subject issuer client_subject client_issuer validation_status +#types time string addr port addr port string string string string bool string string bool vector[string] vector[string] string string string string string +1417039703.224578 CXWv6p3arKYeMETxOg 192.168.4.149 58529 128.32.169.140 443 TLSv10 TLS_RSA_WITH_RC4_128_MD5 - - F - - T FghNi02cFL9n6ttuMa (empty) CN=www.cviis.org,OU=Domain Control Validated CN=Starfield Secure Certificate Authority - G2,OU=http://certs.starfieldtech.com/repository/,O=Starfield Technologies\, Inc.,L=Scottsdale,ST=Arizona,C=US - - unable to get local issuer certificate +1417039705.820093 CjhGID4nQcgTWjvg4c 192.168.4.149 58530 72.167.102.91 443 TLSv12 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 secp256r1 - F - - T Fz7gr4fSm2T2sEyDl,FhjNBG25vvoBO6CS79,FQFHJA20WL56NP6LXk (empty) CN=valid.sfig2.catest.starfieldtech.com,O=Starfield Technologies\, LLC,L=Scottsdale,ST=Arizona,C=US,serialNumber=R-1724741-6,businessCategory=Private Organization,jurisdictionST=Arizona,jurisdictionC=US CN=Starfield Secure Certificate Authority - G2,OU=http://certs.starfieldtech.com/repository/,O=Starfield Technologies\, Inc.,L=Scottsdale,ST=Arizona,C=US - - ok +1417039710.349578 CCvvfg3TEfuqmmG4bh 192.168.4.149 58532 128.32.169.140 443 TLSv10 TLS_RSA_WITH_RC4_128_MD5 - - F - - T FRcFYq3e3hgYkZ8dS1 (empty) CN=www.cviis.org,OU=Domain Control Validated CN=Starfield Secure Certificate Authority - G2,OU=http://certs.starfieldtech.com/repository/,O=Starfield Technologies\, Inc.,L=Scottsdale,ST=Arizona,C=US - - ok +#close 2015-03-09-19-44-42 diff --git a/testing/btest/Baseline/scripts.policy.protocols.ssl.validate-certs/ssl.log b/testing/btest/Baseline/scripts.policy.protocols.ssl.validate-certs/ssl.log deleted file mode 100644 index a464c64670..0000000000 --- a/testing/btest/Baseline/scripts.policy.protocols.ssl.validate-certs/ssl.log +++ /dev/null @@ -1,11 +0,0 @@ -#separator \x09 -#set_separator , -#empty_field (empty) -#unset_field - -#path ssl -#open 2014-08-08-17-13-58 -#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p version cipher curve server_name resumed last_alert next_protocol established cert_chain_fuids client_cert_chain_fuids subject issuer client_subject client_issuer validation_status -#types time string addr port addr port string string string string bool string string bool vector[string] vector[string] string string string string string -1394745602.951961 CXWv6p3arKYeMETxOg 192.168.4.149 60539 87.98.220.10 443 TLSv10 TLS_DHE_RSA_WITH_AES_256_CBC_SHA - - F - - T F1fX1R2cDOzbvg17ye,FqPEQR2eytAQybroyl (empty) CN=www.spidh.org,OU=COMODO SSL,OU=Domain Control Validated CN=COMODO SSL CA,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB - - certificate has expired -1394745618.791420 CjhGID4nQcgTWjvg4c 192.168.4.149 60540 122.1.240.204 443 TLSv10 TLS_RSA_WITH_AES_256_CBC_SHA - - F - - T F6NAbK127LhNBaEe5c,FDhmPt28vyXlGMTxP7,F0ROCKibhE1KntJ1h (empty) CN=www.tobu-estate.com,OU=Terms of use at www.verisign.com/rpa (c)05,O=TOBU RAILWAY Co.\,Ltd.,L=Sumida-ku,ST=Tokyo,C=JP CN=VeriSign Class 3 Secure Server CA - G3,OU=Terms of use at https://www.verisign.com/rpa (c)10,OU=VeriSign Trust Network,O=VeriSign\, Inc.,C=US - - ok -#close 2014-08-08-17-13-58 diff --git a/testing/btest/Traces/tls/missing-intermediate.pcap b/testing/btest/Traces/tls/missing-intermediate.pcap new file mode 100644 index 0000000000000000000000000000000000000000..9f44e3e4d25f2f584096819fd7ac4ace9b758455 GIT binary patch literal 13449 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 V|3k+0?AiK=mf|_W4d$`qe*hjM$^QTV literal 0 HcmV?d00001 diff --git a/testing/btest/scripts/policy/protocols/ssl/validate-certs-cluster.bro b/testing/btest/scripts/policy/protocols/ssl/validate-certs-cluster.bro new file mode 100644 index 0000000000..db9c6cd9da --- /dev/null +++ b/testing/btest/scripts/policy/protocols/ssl/validate-certs-cluster.bro @@ -0,0 +1,37 @@ +# @TEST-SERIALIZE: comm +# +# @TEST-EXEC: btest-bg-run manager-1 "cp ../cluster-layout.bro . && CLUSTER_NODE=manager-1 bro %INPUT" +# @TEST-EXEC: sleep 1 +# @TEST-EXEC: btest-bg-run proxy-1 "cp ../cluster-layout.bro . && CLUSTER_NODE=proxy-1 bro %INPUT" +# @TEST-EXEC: btest-bg-run proxy-2 "cp ../cluster-layout.bro . && CLUSTER_NODE=proxy-2 bro %INPUT" +# @TEST-EXEC: sleep 1 +# @TEST-EXEC: btest-bg-run worker-1 "cp ../cluster-layout.bro . && CLUSTER_NODE=worker-1 bro --pseudo-realtime -C -r $TRACES/tls/missing-intermediate.pcap %INPUT" +# @TEST-EXEC: btest-bg-run worker-2 "cp ../cluster-layout.bro . && CLUSTER_NODE=worker-2 bro --pseudo-realtime -C -r $TRACES/tls/missing-intermediate.pcap %INPUT" +# @TEST-EXEC: btest-bg-wait 10 +# @TEST-EXEC: cat manager-1/ssl*.log > ssl.log +# @TEST-EXEC: TEST_DIFF_CANONIFIER=$SCRIPTS/diff-remove-file-ids btest-diff ssl.log +# + +redef Log::default_rotation_interval = 0secs; + +@TEST-START-FILE cluster-layout.bro +redef Cluster::nodes = { + ["manager-1"] = [$node_type=Cluster::MANAGER, $ip=127.0.0.1, $p=37757/tcp, $workers=set("worker-1", "worker-2")], + ["proxy-1"] = [$node_type=Cluster::PROXY, $ip=127.0.0.1, $p=37758/tcp, $manager="manager-1", $workers=set("worker-1", "worker-2")], + ["proxy-2"] = [$node_type=Cluster::PROXY, $ip=127.0.0.1, $p=37759/tcp, $manager="manager-1", $workers=set("worker-2")], + ["worker-1"] = [$node_type=Cluster::WORKER, $ip=127.0.0.1, $p=37760/tcp, $manager="manager-1", $proxy="proxy-1", $interface="eth0"], + ["worker-2"] = [$node_type=Cluster::WORKER, $ip=127.0.0.1, $p=37761/tcp, $manager="manager-1", $proxy="proxy-1", $interface="eth1"], +}; +@TEST-END-FILE + +event terminate_me() { + terminate(); +} + +event remote_connection_closed(p: event_peer) { + schedule 1sec { terminate_me() }; +} + + +@load base/frameworks/cluster +@load protocols/ssl/validate-certs.bro diff --git a/testing/btest/scripts/policy/protocols/ssl/validate-certs.bro b/testing/btest/scripts/policy/protocols/ssl/validate-certs.bro index 56408483f0..19fca8cb89 100644 --- a/testing/btest/scripts/policy/protocols/ssl/validate-certs.bro +++ b/testing/btest/scripts/policy/protocols/ssl/validate-certs.bro @@ -1,4 +1,7 @@ # @TEST-EXEC: bro -r $TRACES/tls/tls-expired-cert.trace %INPUT -# @TEST-EXEC: btest-diff ssl.log +# @TEST-EXEC: cat ssl.log > ssl-all.log +# @TEST-EXEC: bro -C -r $TRACES/tls/missing-intermediate.pcap %INPUT +# @TEST-EXEC: cat ssl.log >> ssl-all.log +# @TEST-EXEC: btest-diff ssl-all.log -@load protocols/ssl/validate-certs +@load protocols/ssl/validate-certs.bro From 144302d3e7cb07e2001a10a9c0c4009112254578 Mon Sep 17 00:00:00 2001 From: Johanna Amann Date: Mon, 9 Mar 2015 12:53:17 -0700 Subject: [PATCH 2/3] add knob to revert to old validation behavior --- .../policy/protocols/ssl/validate-certs.bro | 19 +++++++++++++++++-- .../ssl.log | 12 ++++++++++++ .../protocols/ssl/validate-certs-no-cache.bro | 6 ++++++ 3 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 testing/btest/Baseline/scripts.policy.protocols.ssl.validate-certs-no-cache/ssl.log create mode 100644 testing/btest/scripts/policy/protocols/ssl/validate-certs-no-cache.bro diff --git a/scripts/policy/protocols/ssl/validate-certs.bro b/scripts/policy/protocols/ssl/validate-certs.bro index d2b3befaed..09000164aa 100644 --- a/scripts/policy/protocols/ssl/validate-certs.bro +++ b/scripts/policy/protocols/ssl/validate-certs.bro @@ -26,6 +26,18 @@ export { global recently_validated_certs: table[string] of string = table() &read_expire=5mins &redef; + ## Use intermediate CA certificate caching when trying to validate + ## certificates. When this is enabled, Bro keeps track of all valid + ## intermediate CA certificates that it has seen in the past. When + ## encountering a host-certificate that cannot be validated because + ## of missing intermediate CA certificate, the cached list is used + ## to try to validate the cert. This is similar to how Firefox is + ## doing certificate validation. + ## Disabling this will usually greatly increase the number of validation + ## warnings that you encounter. Only disable if you want to find misconfigured + ## servers. + global ssl_cache_intermediate_ca: bool = T &redef; + ## Event from a worker to the manager that it has encountered a new ## valid intermediate global intermediate_add: event(key: string, value: vector of opaque of x509); @@ -88,7 +100,10 @@ function cache_validate(chain: vector of opaque of x509): string # if we have a working chain where we did not store the intermediate certs # in our cache yet - do so - if ( result$result_string == "ok" && result?$chain_certs && |result$chain_certs| > 2 ) + if ( ssl_cache_intermediate_ca && + result$result_string == "ok" && + result?$chain_certs && + |result$chain_certs| > 2 ) { local result_chain = result$chain_certs; local icert = x509_parse(result_chain[1]); @@ -121,7 +136,7 @@ event ssl_established(c: connection) &priority=3 # look if we already have a working chain for the issuer of this cert. # If yes, try this chain first instead of using the chain supplied from # the server. - if ( issuer in intermediate_cache ) + if ( ssl_cache_intermediate_ca && issuer in intermediate_cache ) { intermediate_chain[0] = c$ssl$cert_chain[0]$x509$handle; for ( i in intermediate_cache[issuer] ) diff --git a/testing/btest/Baseline/scripts.policy.protocols.ssl.validate-certs-no-cache/ssl.log b/testing/btest/Baseline/scripts.policy.protocols.ssl.validate-certs-no-cache/ssl.log new file mode 100644 index 0000000000..9f33703649 --- /dev/null +++ b/testing/btest/Baseline/scripts.policy.protocols.ssl.validate-certs-no-cache/ssl.log @@ -0,0 +1,12 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path ssl +#open 2015-03-09-19-51-25 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p version cipher curve server_name resumed last_alert next_protocol established cert_chain_fuids client_cert_chain_fuids subject issuer client_subject client_issuer validation_status +#types time string addr port addr port string string string string bool string string bool vector[string] vector[string] string string string string string +1417039703.224578 CXWv6p3arKYeMETxOg 192.168.4.149 58529 128.32.169.140 443 TLSv10 TLS_RSA_WITH_RC4_128_MD5 - - F - - T FghNi02cFL9n6ttuMa (empty) CN=www.cviis.org,OU=Domain Control Validated CN=Starfield Secure Certificate Authority - G2,OU=http://certs.starfieldtech.com/repository/,O=Starfield Technologies\, Inc.,L=Scottsdale,ST=Arizona,C=US - - unable to get local issuer certificate +1417039705.820093 CjhGID4nQcgTWjvg4c 192.168.4.149 58530 72.167.102.91 443 TLSv12 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 secp256r1 - F - - T Fz7gr4fSm2T2sEyDl,FhjNBG25vvoBO6CS79,FQFHJA20WL56NP6LXk (empty) CN=valid.sfig2.catest.starfieldtech.com,O=Starfield Technologies\, LLC,L=Scottsdale,ST=Arizona,C=US,serialNumber=R-1724741-6,businessCategory=Private Organization,jurisdictionST=Arizona,jurisdictionC=US CN=Starfield Secure Certificate Authority - G2,OU=http://certs.starfieldtech.com/repository/,O=Starfield Technologies\, Inc.,L=Scottsdale,ST=Arizona,C=US - - ok +1417039710.349578 CCvvfg3TEfuqmmG4bh 192.168.4.149 58532 128.32.169.140 443 TLSv10 TLS_RSA_WITH_RC4_128_MD5 - - F - - T FRcFYq3e3hgYkZ8dS1 (empty) CN=www.cviis.org,OU=Domain Control Validated CN=Starfield Secure Certificate Authority - G2,OU=http://certs.starfieldtech.com/repository/,O=Starfield Technologies\, Inc.,L=Scottsdale,ST=Arizona,C=US - - unable to get local issuer certificate +#close 2015-03-09-19-51-25 diff --git a/testing/btest/scripts/policy/protocols/ssl/validate-certs-no-cache.bro b/testing/btest/scripts/policy/protocols/ssl/validate-certs-no-cache.bro new file mode 100644 index 0000000000..1bca5b5c50 --- /dev/null +++ b/testing/btest/scripts/policy/protocols/ssl/validate-certs-no-cache.bro @@ -0,0 +1,6 @@ +# @TEST-EXEC: bro -C -r $TRACES/tls/missing-intermediate.pcap %INPUT +# @TEST-EXEC: btest-diff ssl.log + +@load protocols/ssl/validate-certs.bro + +redef SSL::ssl_cache_intermediate_ca = F; From d208c95e9a030142971c1982b101db70677e52f3 Mon Sep 17 00:00:00 2001 From: Johanna Amann Date: Mon, 9 Mar 2015 12:56:55 -0700 Subject: [PATCH 3/3] and still use the hash for notice suppression. --- scripts/policy/protocols/ssl/validate-certs.bro | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/policy/protocols/ssl/validate-certs.bro b/scripts/policy/protocols/ssl/validate-certs.bro index 09000164aa..6e4aba704b 100644 --- a/scripts/policy/protocols/ssl/validate-certs.bro +++ b/scripts/policy/protocols/ssl/validate-certs.bro @@ -131,6 +131,7 @@ event ssl_established(c: connection) &priority=3 local intermediate_chain: vector of opaque of x509 = vector(); local issuer = c$ssl$cert_chain[0]$x509$certificate$issuer; + local hash = c$ssl$cert_chain[0]$sha1; local result: string; # look if we already have a working chain for the issuer of this cert. @@ -168,6 +169,6 @@ event ssl_established(c: connection) &priority=3 local message = fmt("SSL certificate validation failed with (%s)", c$ssl$validation_status); NOTICE([$note=Invalid_Server_Cert, $msg=message, $sub=c$ssl$subject, $conn=c, - $identifier=cat(c$id$resp_h,c$id$resp_p,c$ssl$validation_status)]); + $identifier=cat(c$id$resp_h,c$id$resp_p,hash,c$ssl$validation_status)]); } }