In this two part post, we are going to see how we can utilize the scripting capabilities of Unsniff and Trisul to build our own automated analysis tools. The task here is to scan all HTTPS traffic and print the certificate chain for each session seen.
In Part 1 (this post) : We will use a standalone Unsniff script in Ruby to extract this information from a packet capture.
In Part 2 (next post) – We will see how we can use a Ruby script to connect to a Trisul sensor, pull out all HTTPS certificate chains accessed by a particular IP over 24 hours.
In the following example, the session between 212.149.50.181 and 192.168.1.5 is authenticated by the chain shown below it. The chain is : www.commerzbaking.de is signed by TC Trust Centre which is in turn signed by Cybertrust Global Root which is in turn signed by GTE Cybertrust Global Root.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
Certificate chain for 212.149.50.181 to 192.168.1.5 www.commerzbanking.de (Commerzbank AG) TC TrustCenter Class 4 Extended Validation CA II (TC TrustCenter GmbH) TC TrustCenter Class 4 Extended Validation CA II (TC TrustCenter GmbH) Cybertrust Global Root (Cybertrust, Inc) Cybertrust Global Root (Cybertrust, Inc) GTE CyberTrust Global Root (GTE Corporation) Certificate chain for 174.137.42.65 to 192.168.1.5 www.wireshark.org () PositiveSSL CA (Comodo CA Limited) PositiveSSL CA (Comodo CA Limited) UTN-USERFirst-Hardware (The USERTRUST Network) UTN-USERFirst-Hardware (The USERTRUST Network) AddTrust External CA Root (AddTrust AB) |
Where do we get this information ? As part of the SSL/TLS handshake the remote server sends its certificate chain in a protocol message called Server Certificate. Our Ruby script will look for these messages and print out the chain in the following format..
1 2 3 4 5 6 |
subject1 commonName (organizationName) issuer1 commonName (organizationName) subject2 (same as issuer1) commonName (organizationName) issuer2 commonName (organizationName) ... until the chain ends (ideally in a root CA) |
Using the Unsniff Scripting API
We will write a tiny Ruby script and the Unsniff Scripting API to accomplish this task. (full code available here)
- Pull out all the PDUs containing a Server Certificate.
- For each cert in chain; navigate and print the commonName and organizationName of the subject and issuer.
Key methods in the script
How to pull out all reassembled SSL/TLS PDU records which contain a Server Certificate?
A quick note : Users of Wireshark maybe a bit confused here. In Wireshark the unit of analysis is the link layer packet, i.e Ethernet or Wireless frames. Typically the final packet in the stream contains a link to reassembled content. Unsniff monitors PDUs as top level units. What you see in the PDU sheet are reassembled messages without regard for packet boundaries. TLS is a message layer built on top of a bytestream layer TCP. So we need to work with PDU’s for this example.
Luckily for us, Unsniff sets the Description field of each PDU to contain the names of handshake messages. So we can just select the PDUs which contains “Server Certificate” anywhere in its description..
1 2 3 4 5 6 |
UnsniffDB.PDUIndex.each do |pdu| next unless pdu.Description =~ /Server Certificate/ .. now pdu contains a server cert .. end |
Collect all the certificates in the stack
Frequently a Server Hello + Server Certificate + Server Hello Done are packed intoa single PDU. We only need to work with the “Server Certificate” its easy to select this as the code shows below.
1 2 3 4 5 6 7 8 |
# find the certificate handshake, the string "11 (certificate) " handshake = UWrap.new(pdu.Fields).find do |f| hst = f.FindField("Handshake Type") hst and hst.Value() == "11 (certificate)" end # select all the certs in the chain, the top level field is called "ASN.1Cert" certs = UWrap.new(certstack.SubFields).select { |f| f.Name == "ASN.1Cert" } |
In the above example, we are wrapping the pdu.Fields method in an Enumerable wrapper . This allows us to mix-in methods like Find and Select to the Unsniff Scripting objects which are backed by C++ classes.
How to pull out issuer and subject names ?
At this point, we now have a handle to each certificate in the chain. Our next and final task is to print the issuer and subject details. Our friend is the FindField method
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
# find the subject and issuer fields inside a cert subject = cert.FindField("subject") issuer = cert.FindField("issuer") # get the data which is inside a DirectoryString # we only want commonName and orgName, there are several more # like city, country, street etc. issuer.SubFields.each do |rdn| case rdn.FindField("type").Value when /commonName/ print "Common Name " = rdn.FindField("DirectoryString").Value ; when /organizationName/ print "Org Name = " + rdn.FindField("DirectoryString").Value ; end end |
Running the script
The complete script (xcert.rb) is available at the Unsniff Scripting Samples pages on our new Wiki.
To run this script.
- Download Unsniff Network Analyzer (its a free download). Note that Unsniff is a Windows app.
- Download and install the latest Ruby Windows One Click Installer
- Download the xcert.rb script
- Capture some packets and save it as USNF format. You can also work with PCAP files directly, but you have to modify the script to import the PCAP file into USNF format first. See samples in Import / Export section for hints.
- Run the script
For the analyst with some scripting skillz ?
The philosophy of both Unsniff and Trisul is to put powerful tools in the hands of the analyst. With mid-level skills in Ruby (or even VBScript) you can do amazing things automatically. Take out the tedium of clicking through to perform repeatable tasks. As an exercise you can extend this script to do the following:
- download the root certificates included with Firefox and compare the CAs in your chain for validity
Part 2 : Add Trisul scripting
We have seen how you can do such deep analysis with Unsniff scripting. But this requires you to have a capture file of a manageable size. What if you wanted to
- check all of your traffic during 9AM to 11AM yesterday and print the cert stack of each SSL session
- analyze all SSL sessions during the last week from a workstation 192.168.1.22 – Say you found malware in this machine and want to audit its past activity
- flag all TLS sessions which did not have a valid root certificate, yet the user overrode the Firefox warning and proceeded to complete his/her transaction
For this kind of analysis involving long time ranges and multi-gigabytes of data, Trisul must be used in conjunction with Unsniff. Our latest release of Trisul 2.4 features a very powerful remote scripting API called TRP (Trisul Remote Protocol). Part – 2 will extend this sample to show how you can perform this analysis over large time ranges.
Till next time. Happy packet hunting.
1 thought on “Analyze certificate chains in SSL packet dumps – Part 1”
Comments are closed.