mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 06:38:20 +00:00
Add support for parsing the "caching_sha2_password" auth plugin
This commit is contained in:
parent
6527850487
commit
9cb618c718
6 changed files with 192 additions and 8 deletions
|
@ -23,7 +23,7 @@ refine flow MySQL_Flow += {
|
||||||
connection()->zeek_analyzer()->AnalyzerConfirmation();
|
connection()->zeek_analyzer()->AnalyzerConfirmation();
|
||||||
|
|
||||||
// If the client requested SSL and didn't provide credentials, switch to SSL
|
// If the client requested SSL and didn't provide credentials, switch to SSL
|
||||||
if ( ${msg.version} == 10 && ( ${msg.v10_response.cap_flags} & CLIENT_SSL ) && ${msg.v10_response.credentials}->empty() )
|
if ( ${msg.version} == 10 && ( ${msg.v10_response.cap_flags} & CLIENT_SSL ))
|
||||||
{
|
{
|
||||||
connection()->zeek_analyzer()->StartTLS();
|
connection()->zeek_analyzer()->StartTLS();
|
||||||
return true;
|
return true;
|
||||||
|
@ -31,10 +31,10 @@ refine flow MySQL_Flow += {
|
||||||
|
|
||||||
if ( mysql_handshake )
|
if ( mysql_handshake )
|
||||||
{
|
{
|
||||||
if ( ${msg.version} == 10 && ${msg.v10_response.credentials}->size() > 0 )
|
if ( ${msg.version} == 10 )
|
||||||
zeek::BifEvent::enqueue_mysql_handshake(connection()->zeek_analyzer(),
|
zeek::BifEvent::enqueue_mysql_handshake(connection()->zeek_analyzer(),
|
||||||
connection()->zeek_analyzer()->Conn(),
|
connection()->zeek_analyzer()->Conn(),
|
||||||
zeek::make_intrusive<zeek::StringVal>(c_str(${msg.v10_response.credentials[0].username})));
|
zeek::make_intrusive<zeek::StringVal>(c_str(${msg.v10_response.plain.credentials.username})));
|
||||||
if ( ${msg.version} == 9 )
|
if ( ${msg.version} == 9 )
|
||||||
zeek::BifEvent::enqueue_mysql_handshake(connection()->zeek_analyzer(),
|
zeek::BifEvent::enqueue_mysql_handshake(connection()->zeek_analyzer(),
|
||||||
connection()->zeek_analyzer()->Conn(),
|
connection()->zeek_analyzer()->Conn(),
|
||||||
|
|
|
@ -96,6 +96,11 @@ type LengthEncodedStringArg(first_byte: uint8) = record {
|
||||||
};
|
};
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
%code{
|
||||||
|
const char* PLUGIN_CACHING_SHA2_PASSWORD = "caching_sha2_password";
|
||||||
|
%}
|
||||||
|
|
||||||
|
extern type PLUGIN_CACHING_SHA2_PASSWORD;
|
||||||
extern type to_int;
|
extern type to_int;
|
||||||
|
|
||||||
# Enums
|
# Enums
|
||||||
|
@ -138,6 +143,9 @@ enum command_consts {
|
||||||
enum state {
|
enum state {
|
||||||
CONNECTION_PHASE = 0,
|
CONNECTION_PHASE = 0,
|
||||||
COMMAND_PHASE = 1,
|
COMMAND_PHASE = 1,
|
||||||
|
SHA2_AUTH_PHASE = 2,
|
||||||
|
PUB_KEY_PHASE = 3,
|
||||||
|
SHA2_AUTH_RESP_PHASE = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Expected {
|
enum Expected {
|
||||||
|
@ -158,12 +166,23 @@ enum EOFType {
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Client_Capabilities {
|
enum Client_Capabilities {
|
||||||
|
CLIENT_CONNECT_WITH_DB = 0x00000008,
|
||||||
CLIENT_SSL = 0x00000800,
|
CLIENT_SSL = 0x00000800,
|
||||||
|
CLIENT_PLUGIN_AUTH = 0x00080000,
|
||||||
|
CLIENT_CONNECT_ATTRS = 0x00100000,
|
||||||
# Expects an OK (instead of EOF) after the resultset rows of a Text Resultset.
|
# Expects an OK (instead of EOF) after the resultset rows of a Text Resultset.
|
||||||
CLIENT_DEPRECATE_EOF = 0x01000000,
|
CLIENT_DEPRECATE_EOF = 0x01000000,
|
||||||
|
CLIENT_ZSTD_COMPRESSION_ALGORITHM = 0x04000000,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum SHA2_Atuh_State {
|
||||||
|
REQUEST_PUBLIC_KEY = 2,
|
||||||
|
FAST_AUTH_SUCCESS = 3,
|
||||||
|
PERFORM_FULL_AUTHENTICATION = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
type NUL_String = RE/[^\0]*\0/;
|
type NUL_String = RE/[^\0]*\0/;
|
||||||
|
type EmptyOrNUL_String = RE/([^\0]*\0)?/;
|
||||||
|
|
||||||
# MySQL PDU
|
# MySQL PDU
|
||||||
|
|
||||||
|
@ -195,6 +214,9 @@ type Server_Message(seq_id: uint8, pkt_len: uint32) = case is_initial of {
|
||||||
type Client_Message(state: int) = case state of {
|
type Client_Message(state: int) = case state of {
|
||||||
CONNECTION_PHASE -> connection_phase: Handshake_Response_Packet;
|
CONNECTION_PHASE -> connection_phase: Handshake_Response_Packet;
|
||||||
COMMAND_PHASE -> command_phase : Command_Request_Packet;
|
COMMAND_PHASE -> command_phase : Command_Request_Packet;
|
||||||
|
SHA2_AUTH_PHASE -> sha2_auth_phase : SHA2_Auth_Packet;
|
||||||
|
PUB_KEY_PHASE -> pub_key_phase : Public_Key_Packet;
|
||||||
|
SHA2_AUTH_RESP_PHASE -> sha2_auth_resp_phase : SHA2_Auth_Response_Packet;
|
||||||
};
|
};
|
||||||
|
|
||||||
# Handshake Request
|
# Handshake Request
|
||||||
|
@ -220,7 +242,12 @@ type Handshake_v10 = record {
|
||||||
status_flags : uint16;
|
status_flags : uint16;
|
||||||
capability_flags_2 : uint16;
|
capability_flags_2 : uint16;
|
||||||
auth_plugin_data_len : uint8;
|
auth_plugin_data_len : uint8;
|
||||||
auth_plugin_name : NUL_String;
|
reserved : padding[10];
|
||||||
|
auth_plugin_data_part_2: bytestring &length=13;
|
||||||
|
have_plugin : case ( ( capability_flags_2 << 4 ) & CLIENT_PLUGIN_AUTH ) of {
|
||||||
|
CLIENT_PLUGIN_AUTH -> auth_plugin_name: NUL_String;
|
||||||
|
0x0 -> none : empty;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
type Handshake_v9 = record {
|
type Handshake_v9 = record {
|
||||||
|
@ -240,7 +267,40 @@ type Handshake_Response_Packet = case $context.connection.get_version() of {
|
||||||
|
|
||||||
type Handshake_Credentials_v10 = record {
|
type Handshake_Credentials_v10 = record {
|
||||||
username : NUL_String;
|
username : NUL_String;
|
||||||
password : bytestring &restofdata;
|
password : LengthEncodedString;
|
||||||
|
};
|
||||||
|
|
||||||
|
type Connection_Attribute = record {
|
||||||
|
name : LengthEncodedString;
|
||||||
|
value : LengthEncodedString;
|
||||||
|
};
|
||||||
|
|
||||||
|
type Handshake_Connection_Attributes = record {
|
||||||
|
length : uint8;
|
||||||
|
attrs : Connection_Attribute[] &until($input.length() == 0);
|
||||||
|
} &length = length+1;
|
||||||
|
|
||||||
|
type Handshake_Plain_v10(cap_flags: uint32) = record {
|
||||||
|
credentials: Handshake_Credentials_v10;
|
||||||
|
have_db : case ( cap_flags & CLIENT_CONNECT_WITH_DB ) of {
|
||||||
|
CLIENT_CONNECT_WITH_DB -> database: NUL_String;
|
||||||
|
0x0 -> none_1 : empty;
|
||||||
|
};
|
||||||
|
have_plugin : case ( cap_flags & CLIENT_PLUGIN_AUTH ) of {
|
||||||
|
CLIENT_PLUGIN_AUTH -> auth_plugin_name: EmptyOrNUL_String;
|
||||||
|
0x0 -> none_2 : empty;
|
||||||
|
};
|
||||||
|
have_attrs : case ( cap_flags & CLIENT_CONNECT_ATTRS ) of {
|
||||||
|
CLIENT_CONNECT_ATTRS -> conn_attrs: Handshake_Connection_Attributes;
|
||||||
|
0x0 -> none_3 : empty;
|
||||||
|
};
|
||||||
|
have_zstd : case ( cap_flags & CLIENT_ZSTD_COMPRESSION_ALGORITHM ) of {
|
||||||
|
CLIENT_ZSTD_COMPRESSION_ALGORITHM -> zstd_compression_level: uint8;
|
||||||
|
0x0 -> none_4 : empty;
|
||||||
|
};
|
||||||
|
} &let {
|
||||||
|
update_state: bool = $context.connection.update_state(SHA2_AUTH_PHASE)
|
||||||
|
&if(( cap_flags & CLIENT_PLUGIN_AUTH ) && auth_plugin_name==PLUGIN_CACHING_SHA2_PASSWORD);
|
||||||
};
|
};
|
||||||
|
|
||||||
type Handshake_Response_Packet_v10 = record {
|
type Handshake_Response_Packet_v10 = record {
|
||||||
|
@ -248,7 +308,10 @@ type Handshake_Response_Packet_v10 = record {
|
||||||
max_pkt_size: uint32;
|
max_pkt_size: uint32;
|
||||||
char_set : uint8;
|
char_set : uint8;
|
||||||
pad : padding[23];
|
pad : padding[23];
|
||||||
credentials : Handshake_Credentials_v10[] &until($input.length() == 0);
|
use_ssl : case ( cap_flags & CLIENT_SSL ) of {
|
||||||
|
CLIENT_SSL -> none : empty;
|
||||||
|
default -> plain: Handshake_Plain_v10(cap_flags);
|
||||||
|
};
|
||||||
} &let {
|
} &let {
|
||||||
deprecate_eof: bool = $context.connection.set_deprecate_eof(cap_flags & CLIENT_DEPRECATE_EOF);
|
deprecate_eof: bool = $context.connection.set_deprecate_eof(cap_flags & CLIENT_DEPRECATE_EOF);
|
||||||
};
|
};
|
||||||
|
@ -258,13 +321,37 @@ type Handshake_Response_Packet_v9 = record {
|
||||||
max_pkt_size : uint24le;
|
max_pkt_size : uint24le;
|
||||||
username : NUL_String;
|
username : NUL_String;
|
||||||
auth_response: NUL_String;
|
auth_response: NUL_String;
|
||||||
have_db : case ( cap_flags & 0x8 ) of {
|
have_db : case ( cap_flags & CLIENT_CONNECT_WITH_DB ) of {
|
||||||
0x8 -> database: NUL_String;
|
CLIENT_CONNECT_WITH_DB -> database: NUL_String;
|
||||||
0x0 -> none : empty;
|
0x0 -> none : empty;
|
||||||
};
|
};
|
||||||
password : bytestring &restofdata;
|
password : bytestring &restofdata;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# SHA2 Auth
|
||||||
|
|
||||||
|
type SHA2_Auth_Packet = record {
|
||||||
|
state: bytestring &restofdata;
|
||||||
|
} &let {
|
||||||
|
update_state_1: bool = $context.connection.update_state(COMMAND_PHASE)
|
||||||
|
&if(state[0] == FAST_AUTH_SUCCESS);
|
||||||
|
update_state_2: bool = $context.connection.update_state(PUB_KEY_PHASE)
|
||||||
|
&if(state[1] == REQUEST_PUBLIC_KEY);
|
||||||
|
};
|
||||||
|
|
||||||
|
type Public_Key_Packet = record {
|
||||||
|
pad : uint8;
|
||||||
|
pub_key: bytestring &restofdata;
|
||||||
|
} &let {
|
||||||
|
update_state: bool = $context.connection.update_state(SHA2_AUTH_RESP_PHASE);
|
||||||
|
};
|
||||||
|
|
||||||
|
type SHA2_Auth_Response_Packet = record {
|
||||||
|
data: bytestring &restofdata;
|
||||||
|
} &let {
|
||||||
|
update_state: bool = $context.connection.update_state(COMMAND_PHASE);
|
||||||
|
};
|
||||||
|
|
||||||
# Command Request
|
# Command Request
|
||||||
|
|
||||||
type Command_Request_Packet = record {
|
type Command_Request_Packet = record {
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
#separator \x09
|
||||||
|
#set_separator ,
|
||||||
|
#empty_field (empty)
|
||||||
|
#unset_field -
|
||||||
|
#path mysql
|
||||||
|
#open XXXX-XX-XX-XX-XX-XX
|
||||||
|
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p cmd arg success rows response
|
||||||
|
#types time string addr port addr port string string bool count string
|
||||||
|
XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 127.0.0.1 56494 127.0.0.1 3306 login root F - Got an error reading communication packets
|
||||||
|
XXXXXXXXXX.XXXXXX ClEkJM2Vm5giqnMf4h 127.0.0.1 49352 127.0.0.1 3306 login root T 0 -
|
||||||
|
XXXXXXXXXX.XXXXXX ClEkJM2Vm5giqnMf4h 127.0.0.1 49352 127.0.0.1 3306 query \x00\x01show databases T 0 -
|
||||||
|
XXXXXXXXXX.XXXXXX ClEkJM2Vm5giqnMf4h 127.0.0.1 49352 127.0.0.1 3306 query \x00\x01show tables T 0 -
|
||||||
|
XXXXXXXXXX.XXXXXX ClEkJM2Vm5giqnMf4h 127.0.0.1 49352 127.0.0.1 3306 field_list t T 0 -
|
||||||
|
XXXXXXXXXX.XXXXXX ClEkJM2Vm5giqnMf4h 127.0.0.1 49352 127.0.0.1 3306 query \x00\x01select @@version_comment limit 1 T 0 -
|
||||||
|
XXXXXXXXXX.XXXXXX ClEkJM2Vm5giqnMf4h 127.0.0.1 49352 127.0.0.1 3306 quit (empty) - - -
|
||||||
|
XXXXXXXXXX.XXXXXX C4J4Th3PJpwUYZZ6gc 127.0.0.1 40950 127.0.0.1 3306 login root T 0 -
|
||||||
|
XXXXXXXXXX.XXXXXX C4J4Th3PJpwUYZZ6gc 127.0.0.1 40950 127.0.0.1 3306 query \x00\x01show databases T 0 -
|
||||||
|
XXXXXXXXXX.XXXXXX C4J4Th3PJpwUYZZ6gc 127.0.0.1 40950 127.0.0.1 3306 query \x00\x01show tables T 0 -
|
||||||
|
XXXXXXXXXX.XXXXXX C4J4Th3PJpwUYZZ6gc 127.0.0.1 40950 127.0.0.1 3306 field_list t T 0 -
|
||||||
|
XXXXXXXXXX.XXXXXX C4J4Th3PJpwUYZZ6gc 127.0.0.1 40950 127.0.0.1 3306 query \x00\x01select @@version_comment limit 1 T 0 -
|
||||||
|
XXXXXXXXXX.XXXXXX C4J4Th3PJpwUYZZ6gc 127.0.0.1 40950 127.0.0.1 3306 quit (empty) - - -
|
||||||
|
#close XXXX-XX-XX-XX-XX-XX
|
|
@ -0,0 +1,39 @@
|
||||||
|
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
|
||||||
|
mysql handshake, root
|
||||||
|
mysql error, 1158, Got an error reading communication packets
|
||||||
|
mysql handshake, root
|
||||||
|
mysql ok, 0
|
||||||
|
mysql request, 3, \x00\x01show databases
|
||||||
|
mysql result row, [information_schema]
|
||||||
|
mysql result row, [mysql]
|
||||||
|
mysql result row, [performance_schema]
|
||||||
|
mysql result row, [sys]
|
||||||
|
mysql result row, [test]
|
||||||
|
mysql ok, 0
|
||||||
|
mysql request, 3, \x00\x01show tables
|
||||||
|
mysql result row, [t]
|
||||||
|
mysql ok, 0
|
||||||
|
mysql request, 4, t\x00
|
||||||
|
mysql ok, 0
|
||||||
|
mysql request, 3, \x00\x01select @@version_comment limit 1
|
||||||
|
mysql result row, [MySQL Community Server - GPL]
|
||||||
|
mysql ok, 0
|
||||||
|
mysql request, 1,
|
||||||
|
mysql handshake, root
|
||||||
|
mysql ok, 0
|
||||||
|
mysql request, 3, \x00\x01show databases
|
||||||
|
mysql result row, [information_schema]
|
||||||
|
mysql result row, [mysql]
|
||||||
|
mysql result row, [performance_schema]
|
||||||
|
mysql result row, [sys]
|
||||||
|
mysql result row, [test]
|
||||||
|
mysql ok, 0
|
||||||
|
mysql request, 3, \x00\x01show tables
|
||||||
|
mysql result row, [t]
|
||||||
|
mysql ok, 0
|
||||||
|
mysql request, 4, t\x00
|
||||||
|
mysql ok, 0
|
||||||
|
mysql request, 3, \x00\x01select @@version_comment limit 1
|
||||||
|
mysql result row, [MySQL Community Server - GPL]
|
||||||
|
mysql ok, 0
|
||||||
|
mysql request, 1,
|
BIN
testing/btest/Traces/mysql/caching_sha2_password.trace
Normal file
BIN
testing/btest/Traces/mysql/caching_sha2_password.trace
Normal file
Binary file not shown.
|
@ -0,0 +1,35 @@
|
||||||
|
# @TEST-EXEC: zeek -b -C -r $TRACES/mysql/caching_sha2_password.trace %INPUT >out
|
||||||
|
# @TEST-EXEC: btest-diff out
|
||||||
|
# @TEST-EXEC: btest-diff mysql.log
|
||||||
|
|
||||||
|
@load base/protocols/mysql
|
||||||
|
|
||||||
|
event mysql_ok(c: connection, affected_rows: count)
|
||||||
|
{
|
||||||
|
print "mysql ok", affected_rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
event mysql_eof(c: connection, is_intermediate: bool)
|
||||||
|
{
|
||||||
|
print "mysql eof", is_intermediate;
|
||||||
|
}
|
||||||
|
|
||||||
|
event mysql_result_row(c: connection, row: string_vec)
|
||||||
|
{
|
||||||
|
print "mysql result row", row;
|
||||||
|
}
|
||||||
|
|
||||||
|
event mysql_error(c: connection, code: count, msg: string)
|
||||||
|
{
|
||||||
|
print "mysql error", code, msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
event mysql_command_request(c: connection, command: count, arg: string)
|
||||||
|
{
|
||||||
|
print "mysql request", command, arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
event mysql_handshake(c: connection, username: string)
|
||||||
|
{
|
||||||
|
print "mysql handshake", username;
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue