diff --git a/src/analyzer/protocol/gssapi/gssapi-analyzer.pac b/src/analyzer/protocol/gssapi/gssapi-analyzer.pac index a913441f1d..64e8dd5e50 100644 --- a/src/analyzer/protocol/gssapi/gssapi-analyzer.pac +++ b/src/analyzer/protocol/gssapi/gssapi-analyzer.pac @@ -2,10 +2,12 @@ refine connection GSSAPI_Conn += { %member{ analyzer::Analyzer *ntlm; + analyzer::Analyzer *krb5; %} %init{ - ntlm = analyzer_mgr->InstantiateAnalyzer("NTLM", bro_analyzer->Conn()); + ntlm=0; + krb5=0; %} %cleanup{ @@ -13,13 +15,44 @@ refine connection GSSAPI_Conn += { { ntlm->Done(); delete ntlm; + ntlm=0; + } + + if ( krb5 ) + { + krb5->Done(); + delete krb5; + krb5=0; } %} - function forward_ntlm(data: bytestring, is_orig: bool): bool + function forward_blob(val: GSSAPI_NEG_TOKEN_MECH_TOKEN, is_orig: bool): bool %{ - if ( ntlm ) - ntlm->DeliverStream(${data}.length(), ${data}.begin(), is_orig); + if ( ${val.mech_token}.length() >= 7 && + memcmp("NTLMSSP", ${val.mech_token}.begin(), 7) == 0 ) + { + // ntlmssp + if ( ! ntlm ) + ntlm = analyzer_mgr->InstantiateAnalyzer("NTLM", bro_analyzer()->Conn()); + + if ( ntlm ) + ntlm->DeliverStream(${val.mech_token}.length(), ${val.mech_token}.begin(), is_orig); + } + else if ( ${val.mech_token}.length() == 9 && + (memcmp("\x2a\x86\x48\x86\xf7\x12\x01\x02\x02", ${val.mech_token}.begin(), ${val.mech_token}.length()) == 0 || + memcmp("\x2a\x86\x48\x82\xf7\x12\x01\x02\x02", ${val.mech_token}.begin(), ${val.mech_token}.length()) == 0 ) ) + { + // krb5 && ms-krb5 + if ( ! krb5 ) + krb5 = analyzer_mgr->InstantiateAnalyzer("KRB", bro_analyzer()->Conn()); + + // 0x0100 is a special marker + if ( krb5 && memcmp("\x01\x00", ${val.mech_token}.begin(), 2) == 0 ) + { + krb5->DeliverPacket(${val.mech_token}.length()-2, ${val.mech_token}.begin()+2, is_orig, 0, 0, 0); + } + } + return true; %} @@ -37,7 +70,7 @@ refine connection GSSAPI_Conn += { } refine typeattr GSSAPI_NEG_TOKEN_MECH_TOKEN += &let { - fwd: bool = $context.connection.forward_ntlm(mech_token, is_orig); + fwd: bool = $context.connection.forward_blob(this, is_orig); }; refine typeattr GSSAPI_NEG_TOKEN_RESP_Arg += &let { diff --git a/src/analyzer/protocol/gssapi/gssapi-protocol.pac b/src/analyzer/protocol/gssapi/gssapi-protocol.pac index 024d480f35..abd58d7a4d 100644 --- a/src/analyzer/protocol/gssapi/gssapi-protocol.pac +++ b/src/analyzer/protocol/gssapi/gssapi-protocol.pac @@ -53,3 +53,4 @@ type GSSAPI_NEG_TOKEN_MECH_TOKEN(is_orig: bool) = record { meta : ASN1EncodingMeta; mech_token : bytestring &length=meta.length; }; + diff --git a/src/analyzer/protocol/krb/krb-defs.pac b/src/analyzer/protocol/krb/krb-defs.pac index 681f456e6d..8c918bbb82 100644 --- a/src/analyzer/protocol/krb/krb-defs.pac +++ b/src/analyzer/protocol/krb/krb-defs.pac @@ -19,6 +19,7 @@ enum KRBPADataTypes { PA_PW_SALT = 3, PA_PW_AS_REQ = 16, PA_PW_AS_REP = 17, + PA_ENCTYPE_INFO2 = 19, }; # Defined in RFC 4120 diff --git a/src/analyzer/protocol/krb/krb-padata.pac b/src/analyzer/protocol/krb/krb-padata.pac index 829ae48df8..83ec6fba4c 100644 --- a/src/analyzer/protocol/krb/krb-padata.pac +++ b/src/analyzer/protocol/krb/krb-padata.pac @@ -41,6 +41,14 @@ VectorVal* proc_padata(const KRB_PA_Data_Sequence* data, const BroAnalyzer bro_a vv->Assign(vv->Size(), type_val); break; } + case PA_ENCTYPE_INFO2: + { + RecordVal * type_val = new RecordVal(BifType::Record::KRB::Type_Value); + type_val->Assign(0, new Val(element->data_type(), TYPE_COUNT)); + type_val->Assign(1, bytestring_to_val(element->pa_data_element()->pf_enctype_info2()->salt())); + vv->Assign(vv->Size(), type_val); + break; + } case PA_PW_AS_REQ: { const bytestring& cert = element->pa_data_element()->pa_pk_as_req()->cert(); @@ -91,11 +99,11 @@ VectorVal* proc_padata(const KRB_PA_Data_Sequence* data, const BroAnalyzer bro_a } default: { - if ( ! is_error && element->pa_data_element()->unknown().length() ) + if ( ! is_error && element->pa_data_element()->unknown()->meta()->length() > 0 ) { RecordVal * type_val = new RecordVal(BifType::Record::KRB::Type_Value); type_val->Assign(0, new Val(element->data_type(), TYPE_COUNT)); - type_val->Assign(1, bytestring_to_val(element->pa_data_element()->unknown())); + type_val->Assign(1, bytestring_to_val(element->pa_data_element()->unknown()->content())); vv->Assign(vv->Size(), type_val); } break; @@ -165,13 +173,21 @@ type KRB_PA_Data(is_orig: bool, pkt_type: uint8) = record { # Each pre-auth element type KRB_PA_Data_Element(is_orig: bool, type: int64, length: uint64) = case type of { - PA_TGS_REQ -> pa_tgs_req : KRB_AP_REQ(is_orig); + PA_TGS_REQ -> pa_tgs_req : KRB_PA_AP_REQ_wrapper(is_orig); PA_PW_SALT -> pa_pw_salt : ASN1OctetString; PA_PW_AS_REQ -> pa_pk_as_req : KRB_PA_PK_AS_Req &length=length; PA_PW_AS_REP -> pa_pk_as_rep : KRB_PA_PK_AS_Rep &length=length; - default -> unknown : bytestring &length=length; + PA_ENCTYPE_INFO2 -> pf_enctype_info2 : KRB_PA_ENCTYPE_INFO2 &length=length; + default -> unknown : ASN1Encoding &length=length; }; +type KRB_PA_AP_REQ_wrapper(is_orig: bool) = record { + # Not sure what these two field are, but they need to be + # here for pre-auth ap-req messages. + some_meta1 : ASN1EncodingMeta; + some_meta2 : ASN1EncodingMeta; + req : KRB_AP_REQ(is_orig); +}; # The PKINIT certificate structure for a request type KRB_PA_PK_AS_Req = record { @@ -210,3 +226,12 @@ type KRB_PA_PK_AS_Rep = record { : bytestring &restofdata &transient; }; +type KRB_PA_ENCTYPE_INFO2 = record { + some_meta1 : ASN1EncodingMeta; + some_meta2 : ASN1EncodingMeta; + seq_meta1 : ASN1EncodingMeta; + etype : ASN1Encoding; + seq_meta2 : ASN1EncodingMeta; + string_meta : ASN1EncodingMeta; + salt : bytestring &length=string_meta.length; +}; \ No newline at end of file diff --git a/src/analyzer/protocol/krb/krb-protocol.pac b/src/analyzer/protocol/krb/krb-protocol.pac index afb66de973..a237f6b0fa 100644 --- a/src/analyzer/protocol/krb/krb-protocol.pac +++ b/src/analyzer/protocol/krb/krb-protocol.pac @@ -126,8 +126,6 @@ type KRB_KDC_REP(is_orig: bool, pkt_type: uint8) = record { ### AP_REQ type KRB_AP_REQ(is_orig: bool) = record { - string_meta : ASN1EncodingMeta; - app_meta : ASN1EncodingMeta; seq_meta : ASN1EncodingMeta; pvno : SequenceElement(true); msg_type : SequenceElement(true);