Implement correct parsing of TLS record fragmentation.

Finally. Our test-case is a >400kb certificate with 10,000 alternative
names. :)
This commit is contained in:
Johanna Amann 2015-03-11 18:23:08 -07:00
parent 47de906612
commit ba27bb54d4
11 changed files with 37 additions and 40 deletions

View file

@ -61,19 +61,15 @@ void SSL_Analyzer::DeliverStream(int len, const u_char* data, bool orig)
}
}
void SSL_Analyzer::SendHandshake(uint8 msg_type, uint32 length, const u_char* begin, const u_char* end, bool orig)
void SSL_Analyzer::SendHandshake(const u_char* begin, const u_char* end, bool orig)
{
try
{
handshake_interp->NewData(orig, (const unsigned char*) &msg_type, (const unsigned char*) &msg_type + 1);
uint32 host_length = htonl(length);
handshake_interp->NewData(orig, (const unsigned char*) &host_length, (const unsigned char*) &host_length + sizeof(host_length));
handshake_interp->NewData(orig, begin, end);
}
catch ( const binpac::Exception& e )
{
ProtocolViolation(fmt("Binpac exception: %s", e.c_msg()));
fprintf(stderr, "Handshake exception: %s\n", e.c_msg());
}
}

View file

@ -21,7 +21,7 @@ public:
virtual void DeliverStream(int len, const u_char* data, bool orig);
virtual void Undelivered(uint64 seq, int len, bool orig);
void SendHandshake(uint8 msg_type, uint32 length, const u_char* begin, const u_char* end, bool orig);
void SendHandshake(const u_char* begin, const u_char* end, bool orig);
// Overriden from tcp::TCP_ApplicationAnalyzer.
virtual void EndpointEOF(bool is_orig);

View file

@ -23,11 +23,9 @@ refine connection SSL_Conn += {
return true;
%}
function proc_handshake(rec: SSLRecord, msg_type: uint8, length: uint24, data: bytestring, is_orig: bool) : bool
function proc_handshake(rec: SSLRecord, data: bytestring, is_orig: bool) : bool
%{
fprintf(stderr, "Forwarding to Handshake analyzer: msg_type: %u, length: %u\n", msg_type, to_int()(length));
fprintf(stderr, "%u\n", data.end() - data.begin());
bro_analyzer()->SendHandshake(msg_type, to_int()(length), data.begin(), data.end(), is_orig);
bro_analyzer()->SendHandshake(data.begin(), data.end(), is_orig);
return true;
%}
};
@ -58,5 +56,5 @@ refine typeattr V2ClientMasterKey += &let {
};
refine typeattr Handshake += &let {
proc : bool = $context.connection.proc_handshake(rec, msg_type, length, data, rec.is_orig);
proc : bool = $context.connection.proc_handshake(rec, data, rec.is_orig);
};

View file

@ -43,9 +43,10 @@ refine casetype PlaintextRecord += {
};
type Handshake(rec: SSLRecord) = record {
msg_type: uint8;
length: uint24;
data: bytestring &length=to_int()(length);
# msg_type: uint8;
# length: uint24;
# data: bytestring &length=to_int()(length);
data: bytestring &restofdata;
};
######################################################################

View file

@ -200,10 +200,10 @@ refine connection Handshake_Conn += {
return true;
%}
function proc_handshake(is_orig: bool, msg_type: uint8, length: uint32) : bool
function proc_handshake(is_orig: bool, msg_type: uint8, length: uint24) : bool
%{
BifEvent::generate_ssl_handshake_message(bro_analyzer(),
bro_analyzer()->Conn(), is_orig, msg_type, length);
bro_analyzer()->Conn(), is_orig, msg_type, to_int()(length));
return true;
%}

View file

@ -25,10 +25,9 @@ enum HandshakeType {
type HandshakeRecord(is_orig: bool) = record {
msg_type: uint8;
msg_length: uint32;
msg_length: uint24;
rec: Handshake(this);
# rec: bytestring &length=10 &transient;
} &length=(msg_length + 5);
} &length=(to_int()(msg_length) + 4);
type Handshake(rec: HandshakeRecord) = case rec.msg_type of {
HELLO_REQUEST -> hello_request : HelloRequest(rec);
@ -500,34 +499,14 @@ refine connection Handshake_Conn += {
%member{
uint32 chosen_cipher_;
uint8 msg_type_;
uint32 msg_length_;
%}
%init{
chosen_cipher_ = NO_CHOSEN_CIPHER;
msg_type_ = 0;
msg_length_ = 0;
%}
function chosen_cipher() : int %{ return chosen_cipher_; %}
function msg_type() : uint8 %{ return msg_type_; %}
function msg_length() : uint32 %{ fprintf(stderr, "Got length %d\n", msg_length_); return msg_length_; %}
function set_msg_type(type: uint8) : bool
%{
msg_type_ = type;
return true;
%}
function set_msg_length(len: uint32) : bool
%{
msg_length_ = len;
return true;
%}
function set_cipher(cipher: uint32) : bool
%{
chosen_cipher_ = cipher;

View file

@ -13,6 +13,7 @@ connection Handshake_Conn(bro_analyzer: BroAnalyzer) {
downflow = Handshake_Flow(false);
};
%include ssl-defs.pac
%include tls-handshake-protocol.pac
flow Handshake_Flow(is_orig: bool) {
@ -20,4 +21,3 @@ flow Handshake_Flow(is_orig: bool) {
}
%include tls-handshake-analyzer.pac
%include ssl-defs.pac

View file

@ -0,0 +1 @@
10000

View file

@ -0,0 +1,10 @@
#separator \x09
#set_separator ,
#empty_field (empty)
#unset_field -
#path ssl
#open 2015-03-12-01-22-34
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p version cipher curve server_name resumed last_alert next_protocol established cert_chain_fuids client_cert_chain_fuids subject issuer client_subject client_issuer
#types time string addr port addr port string string string string bool string string bool vector[string] vector[string] string string string string
1426117218.083491 CXWv6p3arKYeMETxOg 192.168.6.86 61454 104.236.167.107 4433 TLSv12 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 secp256r1 104.236.167.107 F - - F FsQdqWuF9t3e4W0d (empty) - - - -
#close 2015-03-12-01-22-34

View file

@ -0,0 +1,12 @@
# Test a heavily fragmented tls connection
# @TEST-EXEC: cat $TRACES/tls/tls-fragmented-handshake.pcap.gz | gunzip | bro -r - %INPUT
# @TEST-EXEC: btest-diff ssl.log
# @TEST-EXEC: btest-diff .stdout
# Certificate has 10,000 alternative names :)
event x509_ext_subject_alternative_name(f: fa_file, ext: X509::SubjectAlternativeName)
{
print |ext$dns|;
}