ssl.log
In the section discussing the http.log
, we noted that most HTTP traffic
is now encrypted and transmitted as HTTPS. Zeek does not create a
https.log
, because Zeek (or other network inspection tools, for that
matter) does not natively recognize HTTP when it is encrypted as HTTPS.
HTTPS is most often encrypted using Transport Layer Security (TLS), which
presents many variants in live traffic. Zeek parses TLS traffic and records its
findings in the ssl.log
. SSL refers to Secure Sockets Layer, an
obsolete predecessor to TLS.
TLS is not restricted to encrypting HTTPS, however. Many other protocols use TLS to encrypt their contents, including Simple Mail Transfer Protocol (SMTP).
Remember that to see the meaning of each field in the ssl.log
, check
SSL::Info
.
Reviewing TLS Versions Seen on the Network
To get an idea of the sorts of TLS traffic running in my network, I ran the
following command to search hundreds of days of Zeek ssl.log
entries:
$ for i in `find . -name ssl*.log.gz`; do zcat $i; done | jq '[."version"]' | grep -v "\]" | grep -v "\[" | sort -n | uniq -c | sort -rn
11279341 "TLSv12"
2877117 "TLSv13"
303084 "unknown-64282"
198154 null
23181 "TLSv10"
5756 "TLSv11"
348 "DTLSv12"
78 "DTLSv10"
TLS 1.0 and 1.1 are obsolete. TLS 1.2 and 1.3 are common, with 1.3 gaining
ground on 1.2 DTLS is a variant used to encrypt UDP traffic. unknown-64282
is apparently a Facebook-created variant of TLS 1.3. Almost 20,000 connections
advertised no TLS version, but were recognized by Zeek as some form of TLS.
To try to see what protocols the TLS might be encrypting, I ran the following
command to search 10 days of Zeek ssl.log
entries:
$ for i in `find ./2020-08-1* -name ssl*.log.gz`; do zcat $i; done | jq -c '[."version", ."next_protocol"]' | sort -n | uniq -c | sort -rn
246868 ["TLSv12",null]
144291 ["TLSv13",null]
86708 ["TLSv12","http/1.1"]
85082 ["TLSv12","h2"]
8450 ["unknown-64282",null]
1966 [null,null]
722 ["TLSv12","apns-pack-v1:4096:4096"]
504 ["TLSv10",null]
234 ["TLSv10","http/1.1"]
154 ["TLSv12","grpc-exp"]
83 ["TLSv11",null]
13 ["DTLSv12",null]
HTTP/1.1
is obviously HTTP. The h2
entry refers to the newer HTTP/2
protocol. The apns-pack-v1:4096:4096
entry appears to refer to Apple Push
Notification Service, which utilizes Application Layer Protocol Negotiation
(ALPN), a TLS extension. The grpc-exp
entry appears to refer to another
ALPN method that uses the gRPC remote procedure call (RPC) library.
With this brief look at the types of TLS traffic one might find in a network
done, it’s time to look at a sample connection that generates a ssl.log
entry.
Preparing to Inspect the ssl.log
To generate network traffic that uses TLS encryption, I retrieved the index page of the https://www.taosecurity.com using curl.
After processing the traffic with Zeek, I had several log files to analyze.
First let’s look at the conn.log
. We will focus on the Web session
itself, and not related traffic like any DNS lookups required to resolve the
hostname to an IP address.
{
"ts": 1598377391.716515,
"uid": "CsukF91Bx9mrqdEaH9",
"id.orig_h": "192.168.4.49",
"id.orig_p": 56718,
"id.resp_h": "13.32.202.10",
"id.resp_p": 443,
"proto": "tcp",
"service": "ssl",
"duration": 0.497269868850708,
"orig_bytes": 929,
"resp_bytes": 31113,
"conn_state": "SF",
"missed_bytes": 0,
"history": "ShADadfF",
"orig_pkts": 37,
"orig_ip_bytes": 2861,
"resp_pkts": 34,
"resp_ip_bytes": 32889
}
We have a client, 192.168.4.49
, interacting with a server,
13.32.202.10
, offering an encrypted service on port 443 TCP. Zeek reports
this as ssl
, but that is a generic term that applies to TLS as well. We can
use the connection identifier, CsukF91Bx9mrqdEaH9
, to find associated Zeek
logs.
Inspecting the ssl.log
When TLS 1.2 Applies
Using the connection identifier, we find the associated ssl.log
entry
for this conversation.
{
"ts": 1598377391.921726,
"uid": "CsukF91Bx9mrqdEaH9",
"id.orig_h": "192.168.4.49",
"id.orig_p": 56718,
"id.resp_h": "13.32.202.10",
"id.resp_p": 443,
"version": "TLSv12",
"cipher": "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
"curve": "secp256r1",
"server_name": "www.taosecurity.com",
"resumed": false,
"next_protocol": "h2",
"established": true,
"cert_chain_fuids": [
"F2XEvj1CahhdhtfvT4",
"FZ7ygD3ERPfEVVohG9",
"F7vklpOKI4yX9wmvh",
"FAnbnR32nIIr2j9XV"
],
"client_cert_chain_fuids": [],
"subject": "CN=www.taosecurity.com",
"issuer": "CN=Amazon,OU=Server CA 1B,O=Amazon,C=US"
}
This is a rich log entry that tells us a lot about the connection. We see that
the server and client agree to speak TLS 1.2, with the designated cipher suite
and elliptic curve. The server name, www.taosecurity.com
appears, which
matches the subject of the certificate presented by the Web server. We can see
that Amazon issued the certificate. The next protocol involved was HTTP/2, as
the next_protocol
field lists h2
. Zeek provides file identifiers for
the four certificates that the server presented to the client. The client did
not present any certificates to the server.
We will use the certificate information when we look at the next log in our
series, the x509.log
.
Inspecting the ssl.log
When TLS 1.3 Applies
The last section showed Zeek’s ssl.log
when visiting a server that
negotiated a TLS 1.2 connection. The following example shows how the situation
changes when the parties use TLS 1.3.
To generate the traffic, I used curl with a switch to try TLS 1.3 encryption.
$ curl -v --tlsv1.3 https://www.taosecurity.com
curl provided the following, in addition to the content of the Web site:
* Connected to www.taosecurity.com (13.32.202.2) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: C:\ProgramData\chocolatey\lib\curl\tools\curl-7.72.0-win64-mingw\bin\curl-ca-bundle.crt
CApath: none
} [5 bytes data]
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
} [512 bytes data]
* TLSv1.3 (IN), TLS handshake, Server hello (2):
{ [122 bytes data]
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
{ [19 bytes data]
* TLSv1.3 (IN), TLS handshake, Certificate (11):
{ [4880 bytes data]
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
{ [264 bytes data]
* TLSv1.3 (IN), TLS handshake, Finished (20):
{ [36 bytes data]
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
} [1 bytes data]
* TLSv1.3 (OUT), TLS handshake, Finished (20):
} [36 bytes data]
* SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256
* ALPN, server accepted to use h2
* Server certificate:
* subject: CN=www.taosecurity.com
* start date: Jun 1 00:00:00 2020 GMT
* expire date: Jul 1 12:00:00 2021 GMT
* subjectAltName: host "www.taosecurity.com" matched cert's "www.taosecurity.com"
* issuer: C=US; O=Amazon; OU=Server CA 1B; CN=Amazon
* SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
} [5 bytes data]
* Using Stream ID: 1 (easy handle 0x1f9ff0c7600)
} [5 bytes data]
> GET / HTTP/2
> Host: www.taosecurity.com
> user-agent: curl/7.72.0
> accept: */*
>
{ [5 bytes data]
* Connection state changed (MAX_CONCURRENT_STREAMS == 128)!
} [5 bytes data]
< HTTP/2 200
< content-type: text/html
< content-length: 28708
< date: Tue, 01 Sep 2020 18:07:59 GMT
< last-modified: Tue, 01 Sep 2020 14:36:01 GMT
< etag: "9a6a530f507d79ba54daa5872b3cad22"
< accept-ranges: bytes
< server: AmazonS3
< vary: Accept-Encoding
< x-cache: Miss from cloudfront
< via: 1.1 c09a013ad199e52fd50ddc5543a72f45.cloudfront.net (CloudFront)
< x-amz-cf-pop: IAD66-C1
< x-amz-cf-id: wXc1bcKla5qIePZ29LBk1fgATzgf1jLYiRvSmnyZcb7Q1eB_ZJSbaA==
<
{ [16032 bytes data]
Note that the certificate details are visible here, because we are looking from the perspective of the Web client, not a passive network observation system.
Here is the conn.log
:
{
"ts": 1598983678.546522,
"uid": "CcJfBs3hXLJn7oHVu7",
"id.orig_h": "192.168.4.142",
"id.orig_p": 58802,
"id.resp_h": "13.32.202.2",
"id.resp_p": 443,
"proto": "tcp",
"service": "ssl",
"duration": 0.13053107261657715,
"orig_bytes": 831,
"resp_bytes": 34650,
"conn_state": "SF",
"missed_bytes": 0,
"history": "ShADadFf",
"orig_pkts": 17,
"orig_ip_bytes": 1523,
"resp_pkts": 30,
"resp_ip_bytes": 35862
}
Here is the ssl.log
:
{
"ts": 1598983678.585087,
"uid": "CcJfBs3hXLJn7oHVu7",
"id.orig_h": "192.168.4.142",
"id.orig_p": 58802,
"id.resp_h": "13.32.202.2",
"id.resp_p": 443,
"version": "TLSv13",
"cipher": "TLS_AES_128_GCM_SHA256",
"curve": "x25519",
"server_name": "www.taosecurity.com",
"resumed": true,
"established": true
}
Note that there is no mention of certificates in the ssl.log
. TLS 1.3
hides these from passive observation systems. We are able to see the server
name, www.taosecurity.com
, however, as well as some information about the
encryption used. These include the TLS version, the cipher, and the elliptic
curve.
Inspecting the ssl.log
When ESNI/ECH Applies
There is one more concern for an analyst working with the ssl.log
.
Encrypted Server Name Indication (ESNI) or Encrypted Client Hello (ECH) are
methods by which the Server Name Identification field is no longer sent as
plain text. The mechanics of this process are less important than the effects
on Zeek ssl.log
entries.
To generate traffic for this example, I used a modern version of Firefox,
configured to support ESNI, and visited a Web site,
https://only.esni.defo.ie/
, that only accepts connections from systems
supporting ESNI.
After processing the traffic with Zeek, I had the following logs.
First, I had two conn.log
entries:
{"ts":1598631659.652789,"uid":"Cg9oVc87cdxWf5Dla","id.orig_h":"192.168.4.142","id.orig_p":63213,"id.resp_h":"185.24.233.103","id.resp_p":443,"proto":"tcp","service":"ssl","duration":5.702061891555786,"orig_bytes":1467,"resp_bytes":3160,"conn_state":"SF","missed_bytes":0,"history":"ShADadTtFf","orig_pkts":11,"orig_ip_bytes":2347,"resp_pkts":8,"resp_ip_bytes":4645}
{"ts":1598631659.331871,"uid":"Cixuvq2LQrbqxU4Y17","id.orig_h":"192.168.4.142","id.orig_p":63210,"id.resp_h":"185.24.233.103","id.resp_p":443,"proto":"tcp","service":"ssl","duration":6.023154020309448,"orig_bytes":2193,"resp_bytes":45269,"conn_state":"SF","missed_bytes":0,"history":"ShADadFf","orig_pkts":14,"orig_ip_bytes":2765,"resp_pkts":37,"resp_ip_bytes":46761}
Second, I had two ssl.log
entries:
{
"ts": 1598631659.431907,
"uid": "Cixuvq2LQrbqxU4Y17",
"id.orig_h": "192.168.4.142",
"id.orig_p": 63210,
"id.resp_h": "185.24.233.103",
"id.resp_p": 443,
"version": "TLSv13",
"cipher": "TLS_AES_256_GCM_SHA384",
"curve": "x25519",
"resumed": true,
"established": true
}
{
"ts": 1598631659.752715,
"uid": "Cg9oVc87cdxWf5Dla",
"id.orig_h": "192.168.4.142",
"id.orig_p": 63213,
"id.resp_h": "185.24.233.103",
"id.resp_p": 443,
"version": "TLSv13",
"cipher": "TLS_AES_256_GCM_SHA384",
"curve": "x25519",
"resumed": true,
"established": true
}
As you can see, there is no identifying information in the ssl.log
here. There are no certificate identifier entries either, although we will talk
about that log type in the next section. As the visit to
https://only.esni.defo.ie/
also used DNS over HTTPs (DoH), there is no DNS
record showing the identity of the remote server, as might be revealed in a
conventional DNS request and response.
As you might expect, this situation has some network security monitoring practitioners concerned by the loss of visibility, and the opportunity for intruders to leverage ESNI-enabled servers and Doh-enabled clients to evade inspection.
Leveraging JA3 and JA3S
JA3 and JA3S are mechanisms to profile the TLS implementations on clients and servers, respectively. These are clever tools to tell analysts more about each end of a connection. To learn more, see the following project page:
https://github.com/salesforce/ja3
When running Zeek with the JA3 and JA3S packages, the scripts will append data
to the ssl.log
as follows.
In the first example, a Web client (curl) connects to the Google Web site using
TLS 1.3. The ssl.log
shows the following entry.
{
"ts": "2020-09-16T14:01:26.194646Z",
"uid": "CH3QeG4kCxFL8eZrs1",
"id.orig_h": "192.168.4.37",
"id.orig_p": 58842,
"id.resp_h": "172.217.15.100",
"id.resp_p": 443,
"version": "TLSv13",
"cipher": "TLS_AES_256_GCM_SHA384",
"curve": "x25519",
"server_name": "www.google.com",
"resumed": true,
"established": true,
"ja3": "3830b2a4fbcea64e74db382e467f5b3b",
"ja3s": "907bf3ecef1c987c889946b737b43de8"
}
Zeek computes the JA3 (client) and JA3S (server) hashes as shown.
In the second example, the same Web client connects to the Corelight Web site.
{
"ts": "2020-09-16T13:58:21.878466Z",
"uid": "CtbyI4sDwTIPROUv6",
"id.orig_h": "192.168.4.37",
"id.orig_p": 49572,
"id.resp_h": "99.86.230.78",
"id.resp_p": 443,
"version": "TLSv13",
"cipher": "TLS_AES_128_GCM_SHA256",
"curve": "x25519",
"server_name": "www.corelight.com",
"resumed": true,
"established": true,
"ja3": "3830b2a4fbcea64e74db382e467f5b3b",
"ja3s": "f4febc55ea12b31ae17cfb7e614afda8"
}
The JA3 (client) hash has stayed the same, but the JA3S (server) hash has changed.
In the third example, the same Web client connects to the TaoSecurity Web site.
{
"ts": "2020-09-16T13:54:57.033503Z",
"uid": "CXc63QyS40XspAmcd",
"id.orig_h": "192.168.4.37",
"id.orig_p": 41608,
"id.resp_h": "99.84.222.6",
"id.resp_p": 443,
"version": "TLSv13",
"cipher": "TLS_AES_128_GCM_SHA256",
"curve": "x25519",
"server_name": "www.taosecurity.com",
"resumed": true,
"established": true,
"ja3": "0bae189478c11bed9d6259ae0ffc9493",
"ja3s": "f4febc55ea12b31ae17cfb7e614afda8"
}
This is an odd result. The JA3 (client) hash has changed, but the JA3S (server) hash has stayed the same. I can explain the server hash staying the same by noting that both the Corelight and TaoSecurity Web sites appear to be hosted by Amazon, meaning the Web servers providing each site are offering the same TLS parameters.
However, I would have expected the JA3 (client) hash to have been the same as the previous two examples. I repeated the connection and got the same JA3 and JA3S hashes.
Conclusion
This section showed that the default ssl.log
provides several details
of interest to defenders, even when inspecting encrypted traffic. As
administrators and intruders deploy newer encryption technologies, however,
defenders will find it increasingly difficult to differentiate among normal,
suspicious, and malicious traffic.