mirror of
https://github.com/zeek/zeek.git
synced 2025-10-06 00:28:21 +00:00
Added is_orig fields to the SSL events and adapted script.
- Added a field named $last_alert to the SSL log. This doesn't even indicate the direction the alert was sent, but we need to start somewhere. - The x509_certificate function has an is_orig field now instead of is_server and it's position in the argument list has moved. - A bit of reorganization and cleanup in the core analyzer.
This commit is contained in:
parent
c8839da069
commit
ec721dffec
8 changed files with 89 additions and 39 deletions
|
@ -13,6 +13,44 @@ export {
|
||||||
[TLSv11] = "TLSv11",
|
[TLSv11] = "TLSv11",
|
||||||
} &default="UNKNOWN";
|
} &default="UNKNOWN";
|
||||||
|
|
||||||
|
const alert_levels: table[count] of string = {
|
||||||
|
[1] = "warning",
|
||||||
|
[2] = "fatal",
|
||||||
|
} &default=function(i: count):string { return fmt("unknown-%d", i); };
|
||||||
|
|
||||||
|
const alert_descriptions: table[count] of string = {
|
||||||
|
[0] = "close_notify",
|
||||||
|
[10] = "unexpected_message",
|
||||||
|
[20] = "bad_record_mac",
|
||||||
|
[21] = "decryption_failed",
|
||||||
|
[22] = "record_overflow",
|
||||||
|
[30] = "decompression_failure",
|
||||||
|
[40] = "handshake_failure",
|
||||||
|
[41] = "no_certificate",
|
||||||
|
[42] = "bad_certificate",
|
||||||
|
[43] = "unsupported_certificate",
|
||||||
|
[44] = "certificate_revoked",
|
||||||
|
[45] = "certificate_expired",
|
||||||
|
[46] = "certificate_unknown",
|
||||||
|
[47] = "illegal_parameter",
|
||||||
|
[48] = "unknown_ca",
|
||||||
|
[49] = "access_denied",
|
||||||
|
[50] = "decode_error",
|
||||||
|
[51] = "decrypt_error",
|
||||||
|
[60] = "export_restriction",
|
||||||
|
[70] = "protocol_version",
|
||||||
|
[71] = "insufficient_security",
|
||||||
|
[80] = "internal_error",
|
||||||
|
[90] = "user_canceled",
|
||||||
|
[100] = "no_renegotiation",
|
||||||
|
[110] = "unsupported_extension",
|
||||||
|
[111] = "certificate_unobtainable",
|
||||||
|
[112] = "unrecognized_name",
|
||||||
|
[113] = "bad_certificate_status_response",
|
||||||
|
[114] = "bad_certificate_hash_value",
|
||||||
|
[115] = "unknown_psk_identity",
|
||||||
|
} &default=function(i: count):string { return fmt("unknown-%d", i); };
|
||||||
|
|
||||||
# http://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xml
|
# http://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xml
|
||||||
const extensions: table[count] of string = {
|
const extensions: table[count] of string = {
|
||||||
[0] = "server_name",
|
[0] = "server_name",
|
||||||
|
@ -526,8 +564,7 @@ export {
|
||||||
[30] = "akid issuer serial mismatch",
|
[30] = "akid issuer serial mismatch",
|
||||||
[31] = "keyusage no certsign",
|
[31] = "keyusage no certsign",
|
||||||
[32] = "unable to get crl issuer",
|
[32] = "unable to get crl issuer",
|
||||||
[33] = "unhandled critical extension"
|
[33] = "unhandled critical extension",
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ export {
|
||||||
subject: string &log &optional;
|
subject: string &log &optional;
|
||||||
not_valid_before: time &log &optional;
|
not_valid_before: time &log &optional;
|
||||||
not_valid_after: time &log &optional;
|
not_valid_after: time &log &optional;
|
||||||
|
last_alert: string &log &optional;
|
||||||
|
|
||||||
cert: string &optional;
|
cert: string &optional;
|
||||||
cert_chain: vector of string &optional;
|
cert_chain: vector of string &optional;
|
||||||
|
@ -112,10 +113,13 @@ event ssl_server_hello(c: connection, version: count, possible_ts: time, session
|
||||||
c$ssl$cipher = cipher_desc[cipher];
|
c$ssl$cipher = cipher_desc[cipher];
|
||||||
}
|
}
|
||||||
|
|
||||||
event x509_certificate(c: connection, cert: X509, is_server: bool, chain_idx: count, chain_len: count, der_cert: string) &priority=5
|
event x509_certificate(c: connection, is_orig: bool, cert: X509, chain_idx: count, chain_len: count, der_cert: string) &priority=5
|
||||||
{
|
{
|
||||||
set_session(c);
|
set_session(c);
|
||||||
|
|
||||||
|
# We aren't doing anything with client certificates yet.
|
||||||
|
if ( is_orig ) return;
|
||||||
|
|
||||||
if ( chain_idx == 0 )
|
if ( chain_idx == 0 )
|
||||||
{
|
{
|
||||||
# Save the primary cert.
|
# Save the primary cert.
|
||||||
|
@ -133,14 +137,21 @@ event x509_certificate(c: connection, cert: X509, is_server: bool, chain_idx: co
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
event ssl_extension(c: connection, code: count, val: string) &priority=5
|
event ssl_extension(c: connection, is_orig: bool, code: count, val: string) &priority=5
|
||||||
{
|
{
|
||||||
set_session(c);
|
set_session(c);
|
||||||
|
|
||||||
if ( extensions[code] == "server_name" )
|
if ( is_orig && extensions[code] == "server_name" )
|
||||||
c$ssl$server_name = sub_bytes(val, 6, |val|);
|
c$ssl$server_name = sub_bytes(val, 6, |val|);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
event ssl_alert(c: connection, is_orig: bool, level: count, desc: count) &priority=5
|
||||||
|
{
|
||||||
|
set_session(c);
|
||||||
|
|
||||||
|
c$ssl$last_alert = alert_descriptions[desc];
|
||||||
|
}
|
||||||
|
|
||||||
event ssl_established(c: connection) &priority=5
|
event ssl_established(c: connection) &priority=5
|
||||||
{
|
{
|
||||||
set_session(c);
|
set_session(c);
|
||||||
|
|
|
@ -10,11 +10,11 @@ export {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
event x509_certificate(c: connection, cert: X509, is_server: bool, chain_idx: count, chain_len: count, der_cert: string) &priority=4
|
event x509_certificate(c: connection, is_orig: bool, cert: X509, chain_idx: count, chain_len: count, der_cert: string) &priority=4
|
||||||
{
|
{
|
||||||
# We aren't tracking client certificates yet and we are also only tracking
|
# We aren't tracking client certificates yet and we are also only tracking
|
||||||
# the primary cert. Watch that this came from an SSL analyzed session too.
|
# the primary cert. Watch that this came from an SSL analyzed session too.
|
||||||
if ( ! is_server || chain_idx != 0 || ! c?$ssl )
|
if ( is_orig || chain_idx != 0 || ! c?$ssl )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
c$ssl$cert_hash = md5_hash(der_cert);
|
c$ssl$cert_hash = md5_hash(der_cert);
|
||||||
|
|
|
@ -33,10 +33,11 @@ export {
|
||||||
const notify_when_cert_expiring_in = 30days &redef;
|
const notify_when_cert_expiring_in = 30days &redef;
|
||||||
}
|
}
|
||||||
|
|
||||||
event x509_certificate(c: connection, cert: X509, is_server: bool, chain_idx: count, chain_len: count, der_cert: string) &priority=3
|
event x509_certificate(c: connection, is_orig: bool, cert: X509, chain_idx: count, chain_len: count, der_cert: string) &priority=3
|
||||||
{
|
{
|
||||||
# If this isn't the host cert or we aren't interested in the server, just return.
|
# If this isn't the host cert or we aren't interested in the server, just return.
|
||||||
if ( chain_idx != 0 ||
|
if ( is_orig ||
|
||||||
|
chain_idx != 0 ||
|
||||||
! c$ssl?$cert_hash ||
|
! c$ssl?$cert_hash ||
|
||||||
! addr_matches_host(c$id$resp_h, notify_certs_expiration) )
|
! addr_matches_host(c$id$resp_h, notify_certs_expiration) )
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -44,10 +44,10 @@ event bro_init() &priority=5
|
||||||
Log::create_stream(Known::CERTS_LOG, [$columns=CertsInfo, $ev=log_known_certs]);
|
Log::create_stream(Known::CERTS_LOG, [$columns=CertsInfo, $ev=log_known_certs]);
|
||||||
}
|
}
|
||||||
|
|
||||||
event x509_certificate(c: connection, cert: X509, is_server: bool, chain_idx: count, chain_len: count, der_cert: string) &priority=3
|
event x509_certificate(c: connection, is_orig: bool, cert: X509, chain_idx: count, chain_len: count, der_cert: string) &priority=3
|
||||||
{
|
{
|
||||||
# Make sure this is the server cert and we have a hash for it.
|
# Make sure this is the server cert and we have a hash for it.
|
||||||
if ( chain_idx != 0 || ! c$ssl?$cert_hash )
|
if ( is_orig || chain_idx != 0 || ! c$ssl?$cert_hash )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
local host = c$id$resp_h;
|
local host = c$id$resp_h;
|
||||||
|
|
|
@ -279,13 +279,13 @@ event ssh_server_version%(c: connection, version: string%);
|
||||||
|
|
||||||
event ssl_client_hello%(c: connection, version: count, possible_ts: time, session_id: string, ciphers: count_set%);
|
event ssl_client_hello%(c: connection, version: count, possible_ts: time, session_id: string, ciphers: count_set%);
|
||||||
event ssl_server_hello%(c: connection, version: count, possible_ts: time, session_id: string, cipher: count, comp_method: count%);
|
event ssl_server_hello%(c: connection, version: count, possible_ts: time, session_id: string, cipher: count, comp_method: count%);
|
||||||
event ssl_extension%(c: connection, code: count, val: string%);
|
event ssl_extension%(c: connection, is_orig: bool, code: count, val: string%);
|
||||||
|
event ssl_alert%(c: connection, is_orig: bool, level: count, desc: count%);
|
||||||
event ssl_established%(c: connection%);
|
event ssl_established%(c: connection%);
|
||||||
event ssl_alert%(c: connection, level: count, desc: count%);
|
|
||||||
|
|
||||||
event x509_certificate%(c: connection, cert: X509, is_server: bool, chain_idx: count, chain_len: count, der_cert: string%);
|
event x509_certificate%(c: connection, is_orig: bool, cert: X509, chain_idx: count, chain_len: count, der_cert: string%);
|
||||||
event x509_extension%(c: connection, data: string%);
|
event x509_extension%(c: connection, is_orig: bool, data: string%);
|
||||||
event x509_error%(c: connection, err: count%);
|
event x509_error%(c: connection, is_orig: bool, err: count%);
|
||||||
|
|
||||||
event stp_create_endp%(c: connection, e: int, is_orig: bool%);
|
event stp_create_endp%(c: connection, e: int, is_orig: bool%);
|
||||||
event stp_resume_endp%(e: int%);
|
event stp_resume_endp%(e: int%);
|
||||||
|
|
|
@ -22,11 +22,17 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
string orig_label(bool is_orig);
|
||||||
void free_X509(void *);
|
void free_X509(void *);
|
||||||
X509* d2i_X509_binpac(X509** px, const uint8** in, int len);
|
X509* d2i_X509_binpac(X509** px, const uint8** in, int len);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%code{
|
%code{
|
||||||
|
string orig_label(bool is_orig)
|
||||||
|
{
|
||||||
|
return string(is_orig ? "originator" :"responder");
|
||||||
|
}
|
||||||
|
|
||||||
void free_X509(void* cert)
|
void free_X509(void* cert)
|
||||||
{
|
{
|
||||||
X509_free((X509*) cert);
|
X509_free((X509*) cert);
|
||||||
|
@ -117,7 +123,7 @@ refine connection SSL_Conn += {
|
||||||
function proc_alert(rec: SSLRecord, level : int, desc : int) : bool
|
function proc_alert(rec: SSLRecord, level : int, desc : int) : bool
|
||||||
%{
|
%{
|
||||||
BifEvent::generate_ssl_alert(bro_analyzer(), bro_analyzer()->Conn(),
|
BifEvent::generate_ssl_alert(bro_analyzer(), bro_analyzer()->Conn(),
|
||||||
level, desc);
|
${rec.is_orig}, level, desc);
|
||||||
return true;
|
return true;
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
@ -200,11 +206,11 @@ refine connection SSL_Conn += {
|
||||||
return true;
|
return true;
|
||||||
%}
|
%}
|
||||||
|
|
||||||
function proc_ssl_extension(type: int, data: bytestring) : bool
|
function proc_ssl_extension(rec: SSLRecord, type: int, data: bytestring) : bool
|
||||||
%{
|
%{
|
||||||
if ( ssl_extension )
|
if ( ssl_extension )
|
||||||
BifEvent::generate_ssl_extension(bro_analyzer(),
|
BifEvent::generate_ssl_extension(bro_analyzer(),
|
||||||
bro_analyzer()->Conn(), type,
|
bro_analyzer()->Conn(), ${rec.is_orig}, type,
|
||||||
new StringVal(data.length(), (const char*) data.data()));
|
new StringVal(data.length(), (const char*) data.data()));
|
||||||
return true;
|
return true;
|
||||||
%}
|
%}
|
||||||
|
@ -231,7 +237,7 @@ refine connection SSL_Conn += {
|
||||||
if ( ! pTemp )
|
if ( ! pTemp )
|
||||||
{
|
{
|
||||||
BifEvent::generate_x509_error(bro_analyzer(), bro_analyzer()->Conn(),
|
BifEvent::generate_x509_error(bro_analyzer(), bro_analyzer()->Conn(),
|
||||||
ERR_get_error());
|
${rec.is_orig}, ERR_get_error());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,8 +263,8 @@ refine connection SSL_Conn += {
|
||||||
StringVal* der_cert = new StringVal(cert.length(), (const char*) cert.data());
|
StringVal* der_cert = new StringVal(cert.length(), (const char*) cert.data());
|
||||||
|
|
||||||
BifEvent::generate_x509_certificate(bro_analyzer(), bro_analyzer()->Conn(),
|
BifEvent::generate_x509_certificate(bro_analyzer(), bro_analyzer()->Conn(),
|
||||||
|
${rec.is_orig},
|
||||||
pX509Cert,
|
pX509Cert,
|
||||||
! ${rec.is_orig},
|
|
||||||
i, certificates->size(),
|
i, certificates->size(),
|
||||||
der_cert);
|
der_cert);
|
||||||
|
|
||||||
|
@ -284,7 +290,7 @@ refine connection SSL_Conn += {
|
||||||
|
|
||||||
StringVal* value = new StringVal(length, (char*)pBuffer);
|
StringVal* value = new StringVal(length, (char*)pBuffer);
|
||||||
BifEvent::generate_x509_extension(bro_analyzer(),
|
BifEvent::generate_x509_extension(bro_analyzer(),
|
||||||
bro_analyzer()->Conn(), value);
|
bro_analyzer()->Conn(), ${rec.is_orig}, value);
|
||||||
OPENSSL_free(pBuffer);
|
OPENSSL_free(pBuffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -445,5 +451,5 @@ refine typeattr CiphertextRecord += &let {
|
||||||
}
|
}
|
||||||
|
|
||||||
refine typeattr SSLExtension += &let {
|
refine typeattr SSLExtension += &let {
|
||||||
proc : bool = $context.connection.proc_ssl_extension(type, data);
|
proc : bool = $context.connection.proc_ssl_extension(rec, type, data);
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,7 +22,6 @@ type uint24 = record {
|
||||||
};
|
};
|
||||||
|
|
||||||
string state_label(int state_nr);
|
string state_label(int state_nr);
|
||||||
string orig_label(bool is_orig);
|
|
||||||
double get_time_from_asn1(const ASN1_TIME * atime);
|
double get_time_from_asn1(const ASN1_TIME * atime);
|
||||||
string handshake_type_label(int type);
|
string handshake_type_label(int type);
|
||||||
%}
|
%}
|
||||||
|
@ -35,7 +34,7 @@ type SSLRecord(is_orig: bool) = record {
|
||||||
head2 : uint8;
|
head2 : uint8;
|
||||||
head3 : uint8;
|
head3 : uint8;
|
||||||
head4 : uint8;
|
head4 : uint8;
|
||||||
rec : RecordText(this, is_orig)[] &length=length, &requires(content_type);
|
rec : RecordText(this)[] &length=length, &requires(content_type);
|
||||||
} &length = length+5, &byteorder=bigendian,
|
} &length = length+5, &byteorder=bigendian,
|
||||||
&let {
|
&let {
|
||||||
version : int =
|
version : int =
|
||||||
|
@ -54,25 +53,25 @@ type SSLRecord(is_orig: bool) = record {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
type RecordText(rec: SSLRecord, is_orig: bool) = case $context.connection.state() of {
|
type RecordText(rec: SSLRecord) = case $context.connection.state() of {
|
||||||
STATE_ABBREV_SERVER_ENCRYPTED, STATE_CLIENT_ENCRYPTED,
|
STATE_ABBREV_SERVER_ENCRYPTED, STATE_CLIENT_ENCRYPTED,
|
||||||
STATE_COMM_ENCRYPTED, STATE_CONN_ESTABLISHED
|
STATE_COMM_ENCRYPTED, STATE_CONN_ESTABLISHED
|
||||||
-> ciphertext : CiphertextRecord(rec, is_orig);
|
-> ciphertext : CiphertextRecord(rec);
|
||||||
default
|
default
|
||||||
-> plaintext : PlaintextRecord(rec, is_orig);
|
-> plaintext : PlaintextRecord(rec);
|
||||||
};
|
};
|
||||||
|
|
||||||
type PossibleEncryptedHandshake(rec: SSLRecord, is_orig: bool) = case $context.connection.state() of {
|
type PossibleEncryptedHandshake(rec: SSLRecord) = case $context.connection.state() of {
|
||||||
# Deal with encrypted handshakes before the server cipher spec change.
|
# Deal with encrypted handshakes before the server cipher spec change.
|
||||||
STATE_CLIENT_FINISHED, STATE_CLIENT_ENCRYPTED
|
STATE_CLIENT_FINISHED, STATE_CLIENT_ENCRYPTED
|
||||||
-> ct : CiphertextRecord(rec, is_orig);
|
-> ct : CiphertextRecord(rec);
|
||||||
default -> hs : Handshake(rec);
|
default -> hs : Handshake(rec);
|
||||||
};
|
};
|
||||||
|
|
||||||
type PlaintextRecord(rec: SSLRecord, is_orig: bool) = case rec.content_type of {
|
type PlaintextRecord(rec: SSLRecord) = case rec.content_type of {
|
||||||
CHANGE_CIPHER_SPEC -> ch_cipher : ChangeCipherSpec(rec);
|
CHANGE_CIPHER_SPEC -> ch_cipher : ChangeCipherSpec(rec);
|
||||||
ALERT -> alert : Alert(rec);
|
ALERT -> alert : Alert(rec);
|
||||||
HANDSHAKE -> handshake : PossibleEncryptedHandshake(rec, is_orig);
|
HANDSHAKE -> handshake : PossibleEncryptedHandshake(rec);
|
||||||
APPLICATION_DATA -> app_data : ApplicationData(rec);
|
APPLICATION_DATA -> app_data : ApplicationData(rec);
|
||||||
V2_ERROR -> v2_error : V2Error(rec);
|
V2_ERROR -> v2_error : V2Error(rec);
|
||||||
V2_CLIENT_HELLO -> v2_client_hello : V2ClientHello(rec);
|
V2_CLIENT_HELLO -> v2_client_hello : V2ClientHello(rec);
|
||||||
|
@ -81,7 +80,7 @@ type PlaintextRecord(rec: SSLRecord, is_orig: bool) = case rec.content_type of {
|
||||||
default -> unknown_record : UnknownRecord(rec);
|
default -> unknown_record : UnknownRecord(rec);
|
||||||
};
|
};
|
||||||
|
|
||||||
type SSLExtension = record {
|
type SSLExtension(rec: SSLRecord) = record {
|
||||||
type: uint16;
|
type: uint16;
|
||||||
data_len: uint16;
|
data_len: uint16;
|
||||||
data: bytestring &length=data_len;
|
data: bytestring &length=data_len;
|
||||||
|
@ -156,10 +155,6 @@ enum AnalyzerState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string orig_label(bool is_orig)
|
|
||||||
{
|
|
||||||
return string(is_orig ? "originator" :"responder");
|
|
||||||
}
|
|
||||||
|
|
||||||
double get_time_from_asn1(const ASN1_TIME * atime)
|
double get_time_from_asn1(const ASN1_TIME * atime)
|
||||||
{
|
{
|
||||||
|
@ -389,7 +384,7 @@ type ClientHello(rec: SSLRecord) = record {
|
||||||
# This weirdness is to deal with the possible existence or absence
|
# This weirdness is to deal with the possible existence or absence
|
||||||
# of the following fields.
|
# of the following fields.
|
||||||
ext_len: uint16[] &until($element == 0 || $element != 0);
|
ext_len: uint16[] &until($element == 0 || $element != 0);
|
||||||
extensions : SSLExtension[] &until($input.length() == 0);
|
extensions : SSLExtension(rec)[] &until($input.length() == 0);
|
||||||
} &let {
|
} &let {
|
||||||
state_changed : bool =
|
state_changed : bool =
|
||||||
$context.connection.transition(STATE_INITIAL,
|
$context.connection.transition(STATE_INITIAL,
|
||||||
|
@ -663,7 +658,7 @@ type UnknownRecord(rec: SSLRecord) = record {
|
||||||
state_changed : bool = $context.connection.lost_track();
|
state_changed : bool = $context.connection.lost_track();
|
||||||
};
|
};
|
||||||
|
|
||||||
type CiphertextRecord(rec: SSLRecord, is_orig: bool) = record {
|
type CiphertextRecord(rec: SSLRecord) = record {
|
||||||
cont : bytestring &restofdata &transient;
|
cont : bytestring &restofdata &transient;
|
||||||
} &let {
|
} &let {
|
||||||
state_changed : bool =
|
state_changed : bool =
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue