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",
|
||||
} &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
|
||||
const extensions: table[count] of string = {
|
||||
[0] = "server_name",
|
||||
|
@ -526,8 +564,7 @@ export {
|
|||
[30] = "akid issuer serial mismatch",
|
||||
[31] = "keyusage no certsign",
|
||||
[32] = "unable to get crl issuer",
|
||||
[33] = "unhandled critical extension"
|
||||
|
||||
[33] = "unhandled critical extension",
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ export {
|
|||
subject: string &log &optional;
|
||||
not_valid_before: time &log &optional;
|
||||
not_valid_after: time &log &optional;
|
||||
last_alert: string &log &optional;
|
||||
|
||||
cert: 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];
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
# We aren't doing anything with client certificates yet.
|
||||
if ( is_orig ) return;
|
||||
|
||||
if ( chain_idx == 0 )
|
||||
{
|
||||
# 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);
|
||||
|
||||
if ( extensions[code] == "server_name" )
|
||||
if ( is_orig && extensions[code] == "server_name" )
|
||||
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
|
||||
{
|
||||
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
|
||||
# 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;
|
||||
|
||||
c$ssl$cert_hash = md5_hash(der_cert);
|
||||
|
|
|
@ -33,10 +33,11 @@ export {
|
|||
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 ( chain_idx != 0 ||
|
||||
if ( is_orig ||
|
||||
chain_idx != 0 ||
|
||||
! c$ssl?$cert_hash ||
|
||||
! addr_matches_host(c$id$resp_h, notify_certs_expiration) )
|
||||
return;
|
||||
|
|
|
@ -44,10 +44,10 @@ event bro_init() &priority=5
|
|||
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.
|
||||
if ( chain_idx != 0 || ! c$ssl?$cert_hash )
|
||||
if ( is_orig || chain_idx != 0 || ! c$ssl?$cert_hash )
|
||||
return;
|
||||
|
||||
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_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_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_extension%(c: connection, data: string%);
|
||||
event x509_error%(c: connection, err: count%);
|
||||
event x509_certificate%(c: connection, is_orig: bool, cert: X509, chain_idx: count, chain_len: count, der_cert: string%);
|
||||
event x509_extension%(c: connection, is_orig: bool, data: string%);
|
||||
event x509_error%(c: connection, is_orig: bool, err: count%);
|
||||
|
||||
event stp_create_endp%(c: connection, e: int, is_orig: bool%);
|
||||
event stp_resume_endp%(e: int%);
|
||||
|
|
|
@ -22,11 +22,17 @@
|
|||
}
|
||||
};
|
||||
|
||||
string orig_label(bool is_orig);
|
||||
void free_X509(void *);
|
||||
X509* d2i_X509_binpac(X509** px, const uint8** in, int len);
|
||||
%}
|
||||
|
||||
%code{
|
||||
string orig_label(bool is_orig)
|
||||
{
|
||||
return string(is_orig ? "originator" :"responder");
|
||||
}
|
||||
|
||||
void free_X509(void* cert)
|
||||
{
|
||||
X509_free((X509*) cert);
|
||||
|
@ -117,7 +123,7 @@ refine connection SSL_Conn += {
|
|||
function proc_alert(rec: SSLRecord, level : int, desc : int) : bool
|
||||
%{
|
||||
BifEvent::generate_ssl_alert(bro_analyzer(), bro_analyzer()->Conn(),
|
||||
level, desc);
|
||||
${rec.is_orig}, level, desc);
|
||||
return true;
|
||||
%}
|
||||
|
||||
|
@ -200,11 +206,11 @@ refine connection SSL_Conn += {
|
|||
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 )
|
||||
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()));
|
||||
return true;
|
||||
%}
|
||||
|
@ -231,7 +237,7 @@ refine connection SSL_Conn += {
|
|||
if ( ! pTemp )
|
||||
{
|
||||
BifEvent::generate_x509_error(bro_analyzer(), bro_analyzer()->Conn(),
|
||||
ERR_get_error());
|
||||
${rec.is_orig}, ERR_get_error());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -257,8 +263,8 @@ refine connection SSL_Conn += {
|
|||
StringVal* der_cert = new StringVal(cert.length(), (const char*) cert.data());
|
||||
|
||||
BifEvent::generate_x509_certificate(bro_analyzer(), bro_analyzer()->Conn(),
|
||||
${rec.is_orig},
|
||||
pX509Cert,
|
||||
! ${rec.is_orig},
|
||||
i, certificates->size(),
|
||||
der_cert);
|
||||
|
||||
|
@ -284,7 +290,7 @@ refine connection SSL_Conn += {
|
|||
|
||||
StringVal* value = new StringVal(length, (char*)pBuffer);
|
||||
BifEvent::generate_x509_extension(bro_analyzer(),
|
||||
bro_analyzer()->Conn(), value);
|
||||
bro_analyzer()->Conn(), ${rec.is_orig}, value);
|
||||
OPENSSL_free(pBuffer);
|
||||
}
|
||||
}
|
||||
|
@ -445,5 +451,5 @@ refine typeattr CiphertextRecord += &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 orig_label(bool is_orig);
|
||||
double get_time_from_asn1(const ASN1_TIME * atime);
|
||||
string handshake_type_label(int type);
|
||||
%}
|
||||
|
@ -35,7 +34,7 @@ type SSLRecord(is_orig: bool) = record {
|
|||
head2 : uint8;
|
||||
head3 : 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,
|
||||
&let {
|
||||
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_COMM_ENCRYPTED, STATE_CONN_ESTABLISHED
|
||||
-> ciphertext : CiphertextRecord(rec, is_orig);
|
||||
-> ciphertext : CiphertextRecord(rec);
|
||||
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.
|
||||
STATE_CLIENT_FINISHED, STATE_CLIENT_ENCRYPTED
|
||||
-> ct : CiphertextRecord(rec, is_orig);
|
||||
-> ct : CiphertextRecord(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);
|
||||
ALERT -> alert : Alert(rec);
|
||||
HANDSHAKE -> handshake : PossibleEncryptedHandshake(rec, is_orig);
|
||||
HANDSHAKE -> handshake : PossibleEncryptedHandshake(rec);
|
||||
APPLICATION_DATA -> app_data : ApplicationData(rec);
|
||||
V2_ERROR -> v2_error : V2Error(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);
|
||||
};
|
||||
|
||||
type SSLExtension = record {
|
||||
type SSLExtension(rec: SSLRecord) = record {
|
||||
type: uint16;
|
||||
data_len: uint16;
|
||||
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)
|
||||
{
|
||||
|
@ -389,7 +384,7 @@ type ClientHello(rec: SSLRecord) = record {
|
|||
# This weirdness is to deal with the possible existence or absence
|
||||
# of the following fields.
|
||||
ext_len: uint16[] &until($element == 0 || $element != 0);
|
||||
extensions : SSLExtension[] &until($input.length() == 0);
|
||||
extensions : SSLExtension(rec)[] &until($input.length() == 0);
|
||||
} &let {
|
||||
state_changed : bool =
|
||||
$context.connection.transition(STATE_INITIAL,
|
||||
|
@ -663,7 +658,7 @@ type UnknownRecord(rec: SSLRecord) = record {
|
|||
state_changed : bool = $context.connection.lost_track();
|
||||
};
|
||||
|
||||
type CiphertextRecord(rec: SSLRecord, is_orig: bool) = record {
|
||||
type CiphertextRecord(rec: SSLRecord) = record {
|
||||
cont : bytestring &restofdata &transient;
|
||||
} &let {
|
||||
state_changed : bool =
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue