Decrypt the krb ticket and send authentication data out.

This commit is contained in:
Julien Wallior 2017-03-15 12:11:10 -04:00
parent 1f777b57b8
commit 98a430c1eb
9 changed files with 137 additions and 4 deletions

View file

@ -4222,6 +4222,7 @@ export {
module KRB; module KRB;
export { export {
const keytab = "/etc/krb5.keytab" &redef;
## KDC Options. See :rfc:`4120` ## KDC Options. See :rfc:`4120`
type KRB::KDC_Options: record { type KRB::KDC_Options: record {
## The ticket to be issued should have its forwardable flag set. ## The ticket to be issued should have its forwardable flag set.
@ -4344,6 +4345,8 @@ export {
cipher : count; cipher : count;
## Cipher text of the ticket ## Cipher text of the ticket
ciphertext : string &optional; ciphertext : string &optional;
## Authentication info
authenticationinfo: string &optional;
}; };
type KRB::Ticket_Vector: vector of KRB::Ticket; type KRB::Ticket_Vector: vector of KRB::Ticket;

View file

@ -9,6 +9,7 @@ bro_plugin_cc(KRB.cc)
bro_plugin_cc(KRB_TCP.cc) bro_plugin_cc(KRB_TCP.cc)
bro_plugin_bif(types.bif) bro_plugin_bif(types.bif)
bro_plugin_bif(events.bif) bro_plugin_bif(events.bif)
bro_plugin_link_library(-lkrb5)
bro_plugin_pac(krb.pac krb-protocol.pac krb-analyzer.pac bro_plugin_pac(krb.pac krb-protocol.pac krb-analyzer.pac
krb-asn1.pac krb-asn1.pac
krb-defs.pac krb-defs.pac

View file

@ -7,13 +7,47 @@
using namespace analyzer::krb; using namespace analyzer::krb;
KRB_Analyzer::KRB_Analyzer(Connection* conn) KRB_Analyzer::KRB_Analyzer(Connection* conn)
: Analyzer("KRB", conn) : Analyzer("KRB", conn),
krb_available(false)
{ {
interp = new binpac::KRB::KRB_Conn(this); interp = new binpac::KRB::KRB_Conn(this);
const char* keytab_filename = BifConst::KRB::keytab->CheckString();
if (access(keytab_filename, R_OK) != 0)
{
reporter->Warning("KRB: Can't access keytab (%s)", keytab_filename);
return;
}
krb5_error_code retval = krb5_init_context(&krb_context);
if (retval)
{
reporter->Warning("KRB: Couldn't initialize the context (%s)", krb5_get_error_message(krb_context, retval));
}
else
{
krb_available = true;
retval = krb5_kt_resolve(krb_context, keytab_filename, &krb_keytab);
if (retval)
{
reporter->Warning("KRB: Couldn't resolve keytab (%s)", krb5_get_error_message(krb_context, retval));
}
}
} }
KRB_Analyzer::~KRB_Analyzer() KRB_Analyzer::~KRB_Analyzer()
{ {
if (krb_available)
{
krb5_error_code retval = krb5_kt_close(krb_context, krb_keytab);
if (retval)
{
reporter->Warning("KRB: Couldn't close keytab (%s)", krb5_get_error_message(krb_context, retval));
}
krb5_free_context(krb_context);
}
delete interp; delete interp;
} }
@ -37,3 +71,67 @@ void KRB_Analyzer::DeliverPacket(int len, const u_char* data, bool orig,
} }
} }
StringVal* KRB_Analyzer::GetAuthenticationInfo(const BroString* principal, const BroString* ciphertext, const bro_uint_t enctype)
{
StringVal* ret = new StringVal("nouser");
if (!krb_available)
{
return ret;
}
BroString delim("/");
int pos = principal->FindSubstring(&delim);
if (pos == -1)
{
reporter->Warning("KRB: Couldn't parse principal (%s)", principal->CheckString());
return ret;
}
BroString* service(principal->GetSubstring(0, pos));
BroString* hostname(principal->GetSubstring(pos + 1, -1));
if (!service || !hostname)
{
reporter->Warning("KRB: Couldn't parse principal (%s)", principal->CheckString());
if (!service)
free(service);
if (!hostname)
free(hostname);
return ret;
}
krb5_principal sprinc;
krb5_error_code retval = krb5_sname_to_principal(krb_context, reinterpret_cast<char*>(hostname->Bytes()), reinterpret_cast<char*>(service->Bytes()), KRB5_NT_SRV_HST, &sprinc);
if (retval)
{
reporter->Warning("KRB: Couldn't generate principal name (%s)", krb5_get_error_message(krb_context, retval));
return ret;
}
free(service);
free(hostname);
krb5_ticket tkt;
tkt.server = sprinc;
tkt.enc_part.enctype = enctype;
tkt.enc_part.ciphertext.data = reinterpret_cast<char*>(ciphertext->Bytes());
tkt.enc_part.ciphertext.length = ciphertext->Len();
retval = krb5_server_decrypt_ticket_keytab(krb_context, krb_keytab, &tkt);
if (retval)
{
reporter->Warning("KRB: Couldn't decrypt ticket (%s)", krb5_get_error_message(krb_context, retval));
return ret;
}
char* cp;
retval = krb5_unparse_name(krb_context, tkt.enc_part2->client, &cp);
if (retval)
{
reporter->Warning("KRB: Couldn't unparse name (%s)", krb5_get_error_message(krb_context, retval));
return ret;
}
free(ret);
ret = new StringVal(cp);
krb5_free_unparsed_name(krb_context, cp);
return ret;
}

View file

@ -5,6 +5,8 @@
#include "krb_pac.h" #include "krb_pac.h"
#include <krb5.h>
namespace analyzer { namespace krb { namespace analyzer { namespace krb {
class KRB_Analyzer : public analyzer::Analyzer { class KRB_Analyzer : public analyzer::Analyzer {
@ -20,9 +22,15 @@ public:
static analyzer::Analyzer* Instantiate(Connection* conn) static analyzer::Analyzer* Instantiate(Connection* conn)
{ return new KRB_Analyzer(conn); } { return new KRB_Analyzer(conn); }
StringVal* GetAuthenticationInfo(const BroString* principal, const BroString* ciphertext, const bro_uint_t enctype);
protected: protected:
binpac::KRB::KRB_Conn* interp; binpac::KRB::KRB_Conn* interp;
bool krb_available;
krb5_context krb_context;
krb5_keytab krb_keytab;
}; };
} } // namespace analyzer::* } } // namespace analyzer::*

View file

@ -22,6 +22,8 @@ public:
// Overriden from tcp::TCP_ApplicationAnalyzer. // Overriden from tcp::TCP_ApplicationAnalyzer.
void EndpointEOF(bool is_orig) override; void EndpointEOF(bool is_orig) override;
StringVal* GetAuthenticationInfo(const BroString* principal, const BroString* ciphertext, const bro_uint_t enctype) { return new StringVal(""); }
static analyzer::Analyzer* Instantiate(Connection* conn) static analyzer::Analyzer* Instantiate(Connection* conn)
{ return new KRB_Analyzer(conn); } { return new KRB_Analyzer(conn); }

View file

@ -245,8 +245,11 @@ refine connection KRB_Conn += {
rv->Assign(0, new Val(${msg.ap_options.use_session_key}, TYPE_BOOL)); rv->Assign(0, new Val(${msg.ap_options.use_session_key}, TYPE_BOOL));
rv->Assign(1, new Val(${msg.ap_options.mutual_required}, TYPE_BOOL)); rv->Assign(1, new Val(${msg.ap_options.mutual_required}, TYPE_BOOL));
RecordVal* rvticket = proc_ticket(${msg.ticket});
StringVal* authenticationinfo = bro_analyzer()->GetAuthenticationInfo(rvticket->Lookup(2)->AsString(), rvticket->Lookup(4)->AsString(), rvticket->Lookup(3)->AsCount());
rvticket->Assign(5, authenticationinfo);
BifEvent::generate_krb_ap_request(bro_analyzer(), bro_analyzer()->Conn(), BifEvent::generate_krb_ap_request(bro_analyzer(), bro_analyzer()->Conn(),
proc_ticket(${msg.ticket}), rv); rvticket, rv);
} }
return true; return true;
%} %}

View file

@ -4,14 +4,22 @@
%extern{ %extern{
#include "types.bif.h" #include "types.bif.h"
#include "events.bif.h" #include "events.bif.h"
namespace analyzer { namespace krb { class KRB_Analyzer; } }
namespace binpac { namespace KRB { class KRB_Conn; } }
typedef analyzer::krb::KRB_Analyzer* KRBAnalyzer;
#include "KRB.h"
%} %}
extern type KRBAnalyzer;
analyzer KRB withcontext { analyzer KRB withcontext {
connection: KRB_Conn; connection: KRB_Conn;
flow: KRB_Flow; flow: KRB_Flow;
}; };
connection KRB_Conn(bro_analyzer: BroAnalyzer) { connection KRB_Conn(bro_analyzer: KRBAnalyzer) {
upflow = KRB_Flow(true); upflow = KRB_Flow(true);
downflow = KRB_Flow(false); downflow = KRB_Flow(false);
}; };

View file

@ -4,14 +4,22 @@
%extern{ %extern{
#include "types.bif.h" #include "types.bif.h"
#include "events.bif.h" #include "events.bif.h"
namespace analyzer { namespace krb_tcp { class KRB_Analyzer; } }
namespace binpac { namespace KRB_TCP { class KRB_Conn; } }
typedef analyzer::krb_tcp::KRB_Analyzer* KRBTCPAnalyzer;
#include "KRB_TCP.h"
%} %}
extern type KRBTCPAnalyzer;
analyzer KRB_TCP withcontext { analyzer KRB_TCP withcontext {
connection: KRB_Conn; connection: KRB_Conn;
flow: KRB_Flow; flow: KRB_Flow;
}; };
connection KRB_Conn(bro_analyzer: BroAnalyzer) { connection KRB_Conn(bro_analyzer: KRBTCPAnalyzer) {
upflow = KRB_Flow(true); upflow = KRB_Flow(true);
downflow = KRB_Flow(false); downflow = KRB_Flow(false);
}; };

View file

@ -1,5 +1,7 @@
module KRB; module KRB;
const keytab: string;
type Error_Msg: record; type Error_Msg: record;
type SAFE_Msg: record; type SAFE_Msg: record;