Adding MySQL TLS Functionality

Hello,

I’m working on adding TLS support for MySQL in the Zeek master branch. Our mysql.log is filling up with a lot of encrypted TLS traffic which isn’t overly helpful to us. Rather than ignore this log entirely, I’d like to just add TLS handshake functionality to the analyzer.

I found that there’ a Client_Capabilities enum type within the MySQL Analyzer that I’ve added the CLIENT_SSL bitmask to, which seems to compare against the right bits in the initial handshake.

However, when I try to create a new TLSHandshake() function in MySQL.cc to call when this type of handshake is detected, similar to how the IMAP analyzer’s StartTLS function, I can’t quite get it to compile:

Error:

Seems like you just need to cast:

  static_cast<analyzer::MySQL::MySQL_Analyzer>(connection()->bro_analyzer())->TLSHandshake();

That is, bro_analyzer() returns an analyzer::Analyzer*, which is the
base class that has no TLSHandshake() method, thus the compiler error.

- Jon

Thanks for the reply!

I’m now getting this error:

You may need to shuffle some of the header includes around, see if the
attached patch helps.

I also had a typo in the example cast, it should have been casting to
a pointer-type with '*', like:

     static_cast<analyzer::MySQL::MySQL_Analyzer*>(connection()->bro_analyzer());

- Jon

mysql-analyzer.patch (1.09 KB)

That worked, thanks! It’s compiling now.

Andrew

So now that it’s compiling, I’m able to work further on this. I was successful in generating ssl.log for SSL connections. However, I’m running into some logic issues where ALL connections are getting flagged as being SSL-enabled handshakes. I’ve narrowed it down to the logic where msg.v10_response.client_ssl is being set to true for both SSL-handshake and non-encrypted connections. This boolean is being generated from:

client_ssl: bool = $context.connection.set_client_ssl(cap_flags & CLIENT_SSL);

Looking at the MySQL documentation, I see that the CLIENT_DEPRECATE_EOF matches correctly: https://github.com/zeek/zeek/blob/master/src/analyzer/protocol/mysql/mysql-protocol.pac#L156
with the MySQL Documentation (0x01000000) (https://dev.mysql.com/doc/internals/en/capability-flags.html#packet-Protocol::CapabilityFlags)

I’ve appended the CLIENT_SSL (Value 0x00000800) to the enum type, which is bitmasked against the Handshake_Response_Packet_v10.cap_flags (uint32) record.

When I printf() the msg.v10_response.client_ssl here::

function proc_mysql_handshake_response_packet(msg: Handshake_Response_Packet): bool
%{

if ( mysql_handshake )
{
if ( ${msg.version} == 10 && ${msg.v10_response.client_ssl}) {
fprintf(stderr, “%u\n”,${msg.v10_response.cap_flags});

I’m seeing the value of 4026597376 set for this variable when I use the zeek cli to parse my MySQL SSL-handshake PCAP. The value that is being returned for this field between Zeek and Wireshark are very different. This is for the same connection:

Zeek returns:
4026597376 (1111 0000 0000 0001 0000 0000 0000 0000)

Wireshark shows:
(Client Capabilities section)
1010 1010 10000 1101

(Extended capabilities section)
0000 0001 1011 1111

I think I’m comparing what should be the same fields. Let me know any of these steps don’t seem right.

Thanks for the help!

Andrew