More SMB/DCERPC/NTLM cleanup.

- NTLM Authentication failures over SMB2 are now marked as such in
   the ntlm.log.
 - Slightly updated filtering mechanism for DCE/RPC operations.
 - Uncommented the atsvc file so it compiles now.
This commit is contained in:
Seth Hall 2016-04-15 10:39:08 -04:00
parent 1fe9e522fb
commit 72f2c2ded2
4 changed files with 78 additions and 61 deletions

View file

@ -25,10 +25,11 @@ export {
operation : string &log &optional; operation : string &log &optional;
}; };
## Set of interface UUID values to ignore. const ignored_operations: table[string] of set[string] = {
const ignored_uuids: set[string] = set( ["winreg"] = set("BaseRegCloseKey", "BaseRegGetVersion", "BaseRegOpenKey", "OpenLocalMachine", "BaseRegEnumKey"),
"e1af8308-5d1f-11c9-91a4-08002b14a0fa" #epmapper ["spoolss"] = set("RpcSplOpenPrinter", "RpcClosePrinter"),
) &redef; ["wkssvc"] = set("NetrWkstaGetInfo"),
} &redef;
} }
type State: record { type State: record {
@ -46,7 +47,7 @@ type BackingState: record {
redef record connection += { redef record connection += {
dce_rpc: Info &optional; dce_rpc: Info &optional;
dce_rpc_state: State &optional; dce_rpc_state: State &optional;
dce_rpc_state_x: table[count] of BackingState &optional; dce_rpc_backing: table[count] of BackingState &optional;
}; };
const ports = { 135/tcp }; const ports = { 135/tcp };
@ -80,17 +81,17 @@ function set_state(c: connection, state_x: BackingState)
function set_session(c: connection, fid: count) function set_session(c: connection, fid: count)
{ {
if ( ! c?$dce_rpc_state_x ) if ( ! c?$dce_rpc_backing )
{ {
c$dce_rpc_state_x = table(); c$dce_rpc_backing = table();
} }
if ( fid !in c$dce_rpc_state_x ) if ( fid !in c$dce_rpc_backing )
{ {
local info = Info($ts=network_time(),$id=c$id,$uid=c$uid); local info = Info($ts=network_time(),$id=c$id,$uid=c$uid);
c$dce_rpc_state_x[fid] = BackingState($info=info, $state=State()); c$dce_rpc_backing[fid] = BackingState($info=info, $state=State());
} }
local state_x = c$dce_rpc_state_x[fid]; local state_x = c$dce_rpc_backing[fid];
set_state(c, state_x); set_state(c, state_x);
} }
@ -99,9 +100,6 @@ event dce_rpc_bind(c: connection, fid: count, uuid: string, ver_major: count, ve
set_session(c, fid); set_session(c, fid);
local uuid_str = uuid_to_string(uuid); local uuid_str = uuid_to_string(uuid);
if ( uuid_str in ignored_uuids )
return;
c$dce_rpc_state$uuid = uuid_str; c$dce_rpc_state$uuid = uuid_str;
c$dce_rpc$endpoint = uuid_endpoint_map[uuid_str]; c$dce_rpc$endpoint = uuid_endpoint_map[uuid_str];
} }
@ -157,8 +155,13 @@ event dce_rpc_response(c: connection, fid: count, opnum: count, stub_len: count)
{ {
# If there is not an endpoint, there isn't much reason to log. # If there is not an endpoint, there isn't much reason to log.
# This can happen if the request isn't seen. # This can happen if the request isn't seen.
if ( c$dce_rpc?$endpoint && c$dce_rpc?$operation ) if ( (c$dce_rpc?$endpoint && (c$dce_rpc$endpoint !in ignored_operations || |ignored_operations[c$dce_rpc$endpoint]| != 0))
||
(c$dce_rpc?$endpoint && c$dce_rpc?$operation &&
c$dce_rpc?$operation && c$dce_rpc$operation !in ignored_operations[c$dce_rpc$endpoint]) )
{
Log::write(LOG, c$dce_rpc); Log::write(LOG, c$dce_rpc);
}
delete c$dce_rpc; delete c$dce_rpc;
} }
} }
@ -169,9 +172,9 @@ event connection_state_remove(c: connection)
return; return;
# TODO: Go through any remaining dce_rpc requests that haven't been processed with replies. # TODO: Go through any remaining dce_rpc requests that haven't been processed with replies.
for ( i in c$dce_rpc_state_x ) for ( i in c$dce_rpc_backing )
{ {
local x = c$dce_rpc_state_x[i]; local x = c$dce_rpc_backing[i];
set_state(c, x); set_state(c, x);
# In the event that the binding wasn't seen, but the pipe # In the event that the binding wasn't seen, but the pipe
@ -186,7 +189,12 @@ event connection_state_remove(c: connection)
} }
} }
if ( c$dce_rpc?$endpoint && c$dce_rpc?$operation ) if ( (c$dce_rpc?$endpoint && |ignored_operations[c$dce_rpc$endpoint]| != 0)
||
(c$dce_rpc?$endpoint && c$dce_rpc?$operation &&
c$dce_rpc?$operation && c$dce_rpc$operation !in ignored_operations[c$dce_rpc$endpoint]) )
{
Log::write(LOG, c$dce_rpc); Log::write(LOG, c$dce_rpc);
}
} }
} }

View file

@ -52,13 +52,13 @@ event ntlm_authenticate(c: connection, request: NTLM::Authenticate) &priority=5
c$ntlm$username = request$user_name; c$ntlm$username = request$user_name;
} }
event gssapi_neg_result(c: connection, state: count) &priority=5 event gssapi_neg_result(c: connection, state: count) &priority=3
{ {
if ( c?$ntlm ) if ( c?$ntlm )
c$ntlm$success = (state == 0); c$ntlm$success = (state == 0);
} }
event gssapi_neg_result(c: connection, state: count) &priority=-5 event gssapi_neg_result(c: connection, state: count) &priority=-3
{ {
if ( c?$ntlm ) if ( c?$ntlm )
{ {
@ -70,6 +70,18 @@ event gssapi_neg_result(c: connection, state: count) &priority=-5
} }
} }
event smb2_message(c: connection, hdr: SMB2::Header, is_orig: bool) &priority=3
{
if ( c?$ntlm &&
( c$ntlm?$username || c$ntlm?$hostname ) &&
hdr$status == 0xC000006D )
{
c$ntlm$success = F;
Log::write(NTLM::LOG, c$ntlm);
c$ntlm$done = T;
}
}
event connection_state_remove(c: connection) &priority=-5 event connection_state_remove(c: connection) &priority=-5
{ {
if ( c?$ntlm && ! c$ntlm$done ) if ( c?$ntlm && ! c$ntlm$done )

View file

@ -1,4 +1,3 @@
# DCE/RPC protocol data unit.
refine connection DCE_RPC_Conn += { refine connection DCE_RPC_Conn += {
%member{ %member{

View file

@ -1,41 +1,39 @@
#%include ../smb/smb-strings.pac
# type ATSVC_Request(unicode: bool, opnum: uint8) = record {
#type ATSVC_Request(unicode: bool, opnum: uint8) = record { empty: padding[1];
# empty: padding[1]; op: case opnum of {
# op: case opnum of { 0 -> add : ATSVC_NetrJobAdd(unicode);
# 0 -> add : ATSVC_NetrJobAdd(unicode); default -> unknown : bytestring &restofdata;
# default -> unknown : bytestring &restofdata; };
# }; };
#};
# type ATSVC_String_Pointer(unicode: bool) = record {
#type ATSVC_String_Pointer(unicode: bool) = record { referent_id : uint32;
# referent_id : uint32; max_count : uint32;
# max_count : uint32; offset : uint32;
# offset : uint32; actual_count : uint32;
# actual_count : uint32; string : bytestring &length=max_count;
# string : SMB_string(unicode, offsetof(string)); };
#};
# type ATSVC_NetrJobAdd(unicode: bool) = record {
#type ATSVC_NetrJobAdd(unicode: bool) = record { server : ATSVC_String_Pointer(unicode);
# server : ATSVC_String_Pointer(unicode); unknown : padding[2];
# unknown : padding[2]; job_time : uint32;
# job_time : uint32; days_of_month : uint32;
# days_of_month : uint32; days_of_week : uint8;
# days_of_week : uint8; flags : uint8;
# flags : uint8; unknown2 : padding[2];
# unknown2 : padding[2]; command : ATSVC_String_Pointer(unicode);
# command : ATSVC_String_Pointer(unicode); };
#};
# type ATSVC_Reply(unicode: bool, opnum: uint16) = record {
#type ATSVC_Reply(unicode: bool, opnum: uint16) = record { op: case opnum of {
# op: case opnum of { 0 -> add: ATSVC_JobID(unicode);
# 0 -> add: ATSVC_JobID(unicode); default -> unknown: bytestring &restofdata;
# default -> unknown: bytestring &restofdata; };
# }; };
#};
# type ATSVC_JobID(unicode: bool) = record {
#type ATSVC_JobID(unicode: bool) = record { id : uint32;
# id : uint32; status : uint32;
# status : uint32; };
#};
#