Merge branch 'krb_changes2' of https://github.com/jwallior/bro

I did some cleanup work.
This commit is contained in:
Johanna Amann 2018-06-01 12:28:27 -07:00
commit 5d5dd65cab
16 changed files with 168 additions and 6 deletions

View file

@ -143,6 +143,13 @@ if (LIBGEOIP_FOUND)
list(APPEND OPTLIBS ${LibGeoIP_LIBRARY})
endif ()
set(USE_KRB5 false)
find_package(LibKrb5)
if (LibKrb5_FOUND)
set(USE_KRB5 true)
list(APPEND OPTLIBS ${LibKrb5_LIBRARY})
endif ()
set(HAVE_PERFTOOLS false)
set(USE_PERFTOOLS_DEBUG false)
set(USE_PERFTOOLS_TCMALLOC false)
@ -294,6 +301,7 @@ message(
"\nAux. Tools: ${INSTALL_AUX_TOOLS}"
"\n"
"\nGeoIP: ${USE_GEOIP}"
"\nKerberos: ${USE_KRB5}"
"\ngperftools found: ${HAVE_PERFTOOLS}"
"\n tcmalloc: ${USE_PERFTOOLS_TCMALLOC}"
"\n debugging: ${USE_PERFTOOLS_DEBUG}"

View file

@ -108,6 +108,9 @@
/* GeoIP geographic lookup functionality */
#cmakedefine USE_GEOIP
/* Define if KRB5 is available */
#cmakedefine USE_KRB5
/* Whether the found GeoIP API supports IPv6 Country Edition */
#cmakedefine HAVE_GEOIP_COUNTRY_EDITION_V6

2
cmake

@ -1 +1 @@
Subproject commit 5080aef1aeeea5bc6b0d8c481ef42f5be2b391a9
Subproject commit 1600554d1d907f4f252f19cf1f55e13d368a936f

View file

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

View file

@ -7,13 +7,47 @@
using namespace analyzer::krb;
KRB_Analyzer::KRB_Analyzer(Connection* conn)
: Analyzer("KRB", conn)
: Analyzer("KRB", conn),
krb_available(false)
{
interp = new binpac::KRB::KRB_Conn(this);
#ifdef USE_KRB5
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));
return;
}
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));
return;
}
krb_available = true;
#endif
}
KRB_Analyzer::~KRB_Analyzer()
{
#ifdef USE_KRB5
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);
}
#endif
delete interp;
}
@ -37,3 +71,60 @@ 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");
#ifdef USE_KRB5
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;
}
std::unique_ptr<BroString> service = unique_ptr<BroString>(principal->GetSubstring(0, pos));
std::unique_ptr<BroString> hostname = unique_ptr<BroString>(principal->GetSubstring(pos + 1, -1));
if ( !service || !hostname )
{
reporter->Warning("KRB: Couldn't parse principal (%s)", principal->CheckString());
return ret;
}
krb5_principal sprinc;
krb5_error_code retval = krb5_sname_to_principal(krb_context, hostname->CheckString(), service->CheckString(), 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;
}
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);
#endif
return ret;
}

View file

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

View file

@ -22,6 +22,8 @@ public:
// Overriden from tcp::TCP_ApplicationAnalyzer.
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)
{ 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(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(),
proc_ticket(${msg.ticket}), rv);
rvticket, rv);
}
return true;
%}

View file

@ -4,14 +4,22 @@
%extern{
#include "types.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 {
connection: KRB_Conn;
flow: KRB_Flow;
};
connection KRB_Conn(bro_analyzer: BroAnalyzer) {
connection KRB_Conn(bro_analyzer: KRBAnalyzer) {
upflow = KRB_Flow(true);
downflow = KRB_Flow(false);
};

View file

@ -4,14 +4,22 @@
%extern{
#include "types.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 {
connection: KRB_Conn;
flow: KRB_Flow;
};
connection KRB_Conn(bro_analyzer: BroAnalyzer) {
connection KRB_Conn(bro_analyzer: KRBTCPAnalyzer) {
upflow = KRB_Flow(true);
downflow = KRB_Flow(false);
};

View file

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

View file

@ -1,3 +1,3 @@
KRB_AP_REQUEST
[pvno=5, realm=VLADG.NET, service_name=krbtgt/VLADG.NET, cipher=18, ciphertext={\x9fY\xd0f\x8dS\xf4I\x88\x04\xfa\xc1\xd8m\xa2\xb7+\xbb\x19\xcag\x0c\x13\xd1g*\xfc\x18\xd1\xb1\x80!\xbd\x85\xec\xf9\x9b\xfa-\x18\xb6\xf5h\x91\xe7\x99\xf4\xdb\x93\xa0\xc7\x90\x1e\xa9\x95v\xd3\x12\xfa,9\x1d\x0b\xd0\xa1\xd25\x0f\x1f[G\xdf\xd0\xbbd\x06$2\xd1\xae\x130qZiY\x07@\xe9\xf9\xff\xa4\x9a\xd4\x09\xf0\x0d\xc1R\x10M\xbdKOV\xfd\xf6\x13\xf6\x9a\x95N\xdf!\xf6x\x94\xd8j\xa5\xdcp\xa8\x04\x99\x02x\xdb$\xd8\xfa_o\x8dV\xc8\x0a\xfe\x00\xf3&c\x0c8\xd1\xd0\xe9\x8e\xab\xfe&\xfe\x00\x8d$\x98I\xe5\x8d\x94rM4%\xd8\xfe\xa9\x08\x06\xc6\x95H7\xf7HCq\xb9\x0d$\x95?\x83B\x82\xdd\xea\xc3f3\xcc\xbb\x09\x0d-\x09;\xa6i%\xcd\xba\x11\xd4\xe0\x12w\xd0G&\xdaj\x82\x7f;\xf3\x1d\x10\xa4l\x06\x16l\x1bc\xa1\xd1\x15!\x00\x8a\xff\x8a\x06\xe7U^:<d\xba"\x02I\xf0\xce\xc7\xad\xb2]
[pvno=5, realm=VLADG.NET, service_name=krbtgt/VLADG.NET, cipher=18, ciphertext={\x9fY\xd0f\x8dS\xf4I\x88\x04\xfa\xc1\xd8m\xa2\xb7+\xbb\x19\xcag\x0c\x13\xd1g*\xfc\x18\xd1\xb1\x80!\xbd\x85\xec\xf9\x9b\xfa-\x18\xb6\xf5h\x91\xe7\x99\xf4\xdb\x93\xa0\xc7\x90\x1e\xa9\x95v\xd3\x12\xfa,9\x1d\x0b\xd0\xa1\xd25\x0f\x1f[G\xdf\xd0\xbbd\x06$2\xd1\xae\x130qZiY\x07@\xe9\xf9\xff\xa4\x9a\xd4\x09\xf0\x0d\xc1R\x10M\xbdKOV\xfd\xf6\x13\xf6\x9a\x95N\xdf!\xf6x\x94\xd8j\xa5\xdcp\xa8\x04\x99\x02x\xdb$\xd8\xfa_o\x8dV\xc8\x0a\xfe\x00\xf3&c\x0c8\xd1\xd0\xe9\x8e\xab\xfe&\xfe\x00\x8d$\x98I\xe5\x8d\x94rM4%\xd8\xfe\xa9\x08\x06\xc6\x95H7\xf7HCq\xb9\x0d$\x95?\x83B\x82\xdd\xea\xc3f3\xcc\xbb\x09\x0d-\x09;\xa6i%\xcd\xba\x11\xd4\xe0\x12w\xd0G&\xdaj\x82\x7f;\xf3\x1d\x10\xa4l\x06\x16l\x1bc\xa1\xd1\x15!\x00\x8a\xff\x8a\x06\xe7U^:<d\xba"\x02I\xf0\xce\xc7\xad\xb2, authenticationinfo=nouser]
[use_session_key=F, mutual_required=F]

View file

@ -0,0 +1 @@
wallior@DS.SUSQ.COM

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,21 @@
# This test verifies that given the proper keytab file, the
# Kerberos analyzer can open the AD ticket in the Negociate
# Protocol Request and find the user.
#
# @TEST-REQUIRES: grep -q "#define USE_KRB5" $BUILD/bro-config.h
#
# @TEST-COPY-FILE: ${TRACES}/krb/smb2_krb.keytab
# @TEST-EXEC: bro -b -C -r $TRACES/krb/smb2_krb.pcap %INPUT
# @TEST-EXEC: btest-diff .stdout
redef KRB::keytab = "smb2_krb.keytab";
global monitor_ports: set[port] = { 445/tcp, 139/tcp } &redef;
event bro_init() &priority=5{
Analyzer::register_for_ports(Analyzer::ANALYZER_SMB, monitor_ports);
}
event krb_ap_request(c: connection, ticket: KRB::Ticket, opts: KRB::AP_Options){
print ticket$authenticationinfo;
}