Patrick Kelley 04da5c1250 Inital
2025-05-28 14:31:31 -04:00

356 lines
10 KiB
Plaintext
Executable File

#
# File: main.zeek
# Created: 20180701
# Updated: 20201009
#
# Copyright 2018 The MITRE Corporation. All Rights Reserved.
# Approved for public release. Distribution unlimited. Case number 18-3868.
#
@if ((Version::info$major == 2) && (Version::info$minor <= 5))
# Use this syntax for Bro v2.5.x and below
@load policy/protocols/smb
@else
# Use this syntax for Bro v2.6.x and above
@load base/protocols/smb
@endif
@load base/protocols/dce-rpc
@load base/frameworks/files
@load base/frameworks/notice
@load base/frameworks/sumstats
module BZAR;
export
{
# NOTICE - Raise Notices for these ATT&CK Tactics & Categories
redef enum Notice::Type +=
{
ATTACK::Credential_Access,
ATTACK::Defense_Evasion,
ATTACK::Discovery,
ATTACK::Execution,
ATTACK::Impact,
ATTACK::Lateral_Movement,
ATTACK::Lateral_Movement_and_Execution,
ATTACK::Lateral_Movement_Extracted_File,
ATTACK::Lateral_Movement_Multiple_Attempts,
ATTACK::Persistence,
};
# Full descriptive name of each ATT&CK Technique
# Used in BZAR Reporting
const attack_info : table[string] of string =
{
["t1003.006"] = "T1003.006 OS Credential Dumping: DCSync",
["t1547.004"] = "T1547.004 Boot or Logon Autostart Execution: Winlogon Helper DLL",
["t1547.010"] = "T1547.010 Boot or Logon Autostart Execution: Port Monitors",
["t1016"] = "T1016 System Network Configuration Discovery",
["t1018"] = "T1018 Remote System Discovery",
["t1033"] = "T1033 System Owner/User Discovery",
["t1569.002"] = "T1569.002 System Services: Service Execution",
["t1047"] = "T1047 WMI",
["t1049"] = "T1049 System Network Connections Discovery",
["t1053.002"] = "T1053.002 Scheduled Task/Job: At",
["t1053.005"] = "T1053.005 Scheduled Task/Job: Scheduled Task",
["t1069"] = "T1069 Permission Groups Discovery",
["t1070.001"] = "T1070.001 Indicator Removal on Host: Clear Windows Event Logs",
["t1021.002"] = "T1021.002 Remote Services: SMB/Windows Admin Shares",
["t1082"] = "T1082 System Information Discovery",
["t1083"] = "T1083 File and Directory Discovery",
["t1087"] = "T1087 Account Discovery",
["t1570"] = "T1570 Lateral Tool Transfer",
["t1124"] = "T1124 System Time Discovery",
["t1135"] = "T1135 Network Share Discovery",
["t1529"] = "T1529 System Shutdown/Reboot",
} &redef;
type EndpointWhitelist : record
{
# Specify IP Addresses to ignore
orig_addrs : set[addr] &optional;
resp_addrs : set[addr] &optional;
# Specify IP Subnets to ignore
orig_subnets : set[subnet] &optional;
resp_subnets : set[subnet] &optional;
# Specify Host Names to ignore
orig_names : set[string] &optional;
resp_names : set[string] &optional;
} &redef;
}
#end export
#
# Helper Functions
#
function whitelist_test( orig_h : addr, resp_h : addr, w : BZAR::EndpointWhitelist ) : bool
{
local match : bool = F;
#
# Check if Endpoint IP Addrs are Associated with Whitelist
#
if ( w?$orig_addrs && (orig_h in w$orig_addrs) )
{
match = T;
}
else if ( w?$resp_addrs && (resp_h in w$resp_addrs) )
{
match = T;
}
else if ( w?$orig_subnets && (orig_h in w$orig_subnets) )
{
match = T;
}
else if ( w?$resp_subnets && (resp_h in w$resp_subnets) )
{
match = T;
}
else if ( w?$orig_names )
{
@if ( Version::number >= 50000 )
when [w, orig_h, match] ( (local n1 = lookup_addr(orig_h)) && (n1 in w$orig_names) ) {
@else
when ( (local n1 = lookup_addr(orig_h)) && (n1 in w$orig_names) ) {
@endif
match = T;
}
timeout BZAR::whitelist_dns_timeout
{
match = F;
}
}
else if ( w?$resp_names )
{
@if ( Version::number >= 50000 )
when [w, resp_h, match] ( (local n2 = lookup_addr(resp_h)) && (n2 in w$resp_names) ) {
@else
when ( (local n2 = lookup_addr(resp_h)) && (n2 in w$resp_names) ) {
@endif
match = T;
}
timeout BZAR::whitelist_dns_timeout
{
match = F;
}
}
return match;
}
function sort_func( a : double, b : double ) : int
{
if ( a < b)
return -1;
else
return 1;
}
#
# BZAR Initialization
#
@if ( Version::info$major >= 3 )
# Use this syntax for Zeek v3.x.x and above
event zeek_init()
{
@else
# Use this syntax for Bro v2.x.x and below
event bro_init()
{
@endif
# 1- SumStats Analytics for ATT&CK Lateral Movement and Execution
#
# Description:
# Use SumStats to raise a Bro/Zeek Notice event if an SMB Lateral Movement
# indicator (e.g., SMB File Write to a Windows Admin File Share: ADMIN$ or
# C$ only) is observed together with a DCE-RPC Execution indicator against
# the same (targeted) host, within a specified period of time.
#
# Relevant ATT&CK Technique(s):
# T1021.002 Remote Services: SMB/Windows Admin Shares (file shares only, not
# named pipes) && T1570 Lateral Tool Transfer && (T1569.002 System Services:
# Service Execution|| T1047 WMI || T1053.002 Scheduled Task/Job: At ||
# T1053.005 Scheduled Task/Job: Scheduled Task)
#
# Relevant Indicator(s) Detected by Bro/Zeek:
# (a) smb1_write_andx_response::c$smb_state$path contains ADMIN$ or C$
# (b) smb2_write_request::c$smb_state$path contains ADMIN$ or C$**
# (c) dce_rpc_response::c$dce_rpc$endpoint + c$dce_rpc$operation contains
# any of the following:
# BZAR::t1569_002_rpc_strings
# BZAR::t1047_rpc_strings
# BZAR::t1053_002_rpc_strings
# BZAR::t1053_005_rpc_strings
#
# **NOTE: Preference would be to detect 'smb2_write_response'
# event (instead of 'smb2_write_request'), because it
# would confirm the file was actually written to the
# remote destination. Unfortuantely, Bro/Zeek does
# not have an event for that SMB message-type yet.
#
# Globals (defined in bzar_config_options.zeek):
# bzar1_epoch
# bzar1_limit
local bzar1 = SumStats::Reducer(
$stream="attack_lm_ex",
$apply=set(SumStats::SUM, SumStats::MAX, SumStats::MIN)
);
SumStats::create([
$name = "attack_lm_ex_notice",
$reducers = set(bzar1),
$epoch = bzar1_epoch,
$threshold = bzar1_limit,
$threshold_val (key:SumStats::Key, result:SumStats::Result) =
{
return result["attack_lm_ex"]$sum;
},
$threshold_crossed(key:SumStats::Key, result:SumStats::Result) =
{
local r = result["attack_lm_ex"];
# Ensure at least one RPC_EXEC was observed and
# at least one SMB_WRITE was observed
if ( r$max == 1000 && r$min == 1 )
{
local s = fmt("Detected activity against host %s, total score %.0f within timeframe %s", key$host, r$sum, bzar1_epoch);
# Raise Notice
NOTICE([$note=ATTACK::Lateral_Movement_and_Execution,
$msg=s]
);
}
}
]);
# 2- SumStats Analytics for ATTACK Lateral Movement (Multiple Attempts)
#
# Description:
# Use SumStats to raise a Bro/Zeek Notice event if multiple SMB Lateral
# Movement indicators (e.g., multiple attempts to connect to a Windows Admin
# File Share: ADMIN$ or C$ only) are observed originating from the same host,
# regardless of write-attempts and regardless of whether or not any connection
# is successful --just connection attempts-- within a specified period of time.
#
# Relevant ATT&CK Technique(s):
# T1021.002 SMB/Windows Admin Shares (file shares only, not named pipes)
#
# Relevant Indicator(s) Detected by Bro/Zeek:
# (a) smb1_tree_connect_andx_request::c$smb_state$path contains ADMIN$ or C$
# (b) smb2_tree_connect_request::c$smb_state$path contains ADMIN$ or C$
#
# Globals (defined in bzar_config_options.zeek):
# bzar2_epoch
# bzar2_limit
local bzar2 = SumStats::Reducer(
$stream="attack_lm_multiple_t1021_002",
$apply=set(SumStats::SUM)
);
SumStats::create([
$name = "attack_t1021_002_notice",
$reducers = set(bzar2),
$epoch = bzar2_epoch,
$threshold_series = sort(bzar2_limit, sort_func),
$threshold_val (key:SumStats::Key, result:SumStats::Result) =
{
return result["attack_lm_multiple_t1021_002"]$sum;
},
$threshold_crossed(key:SumStats::Key, result:SumStats::Result) =
{
local s = fmt("Detected T1021.002 Admin File Share activity from host %s, total attempts %.0f within timeframe %s", key$host, result["attack_lm_multiple_t1021_002"]$sum, bzar2_epoch);
# Raise Notice
NOTICE([$note=ATTACK::Lateral_Movement_Multiple_Attempts,
$msg=s]
);
}
]);
# 3- SumStats Analytics for ATTACK Discovery
#
# Description:
# Use SumStats to raise a Bro/Zeek Notice event if multiple instances of
# DCE-RPC Discovery indicators are observed originating from the same host,
# within a specified period of time.
#
# Relevant ATT&CK Technique(s):
# T1016 System Network Configuration Discovery
# T1018 Remote System Discovery
# T1033 System Owner/User Discovery
# T1069 Permission Groups Discovery
# T1082 System Information Discovery
# T1083 File & Directory Discovery
# T1087 Account Discovery
# T1124 System Time Discovery
# T1135 Network Share Discovery
#
# Relevant Indicator(s) Detected by Bro/Zeek:
# (a) dce_rpc_response::c$dce_rpc$endpoint + c$dce_rpc$operation contains
# any of the following:
# BZAR::t1016_rpc_strings
# BZAR::t1018_rpc_strings
# BZAR::t1033_rpc_strings
# BZAR::t1069_rpc_strings
# BZAR::t1082_rpc_strings
# BZAR::t1083_rpc_strings
# BZAR::t1087_rpc_strings
# BZAR::t1124_rpc_strings
# BZAR::t1135_rpc_strings
#
# Globals (defined in bzar_config_options.zeek):
# bzar3_epoch
# bzar3_limit
local bzar3 = SumStats::Reducer(
$stream="attack_discovery",
$apply=set(SumStats::SUM)
);
SumStats::create([
$name = "attack_discovery_notice",
$reducers = set(bzar3),
$epoch = bzar3_epoch,
$threshold_series = sort(bzar3_limit, sort_func),
$threshold_val (key:SumStats::Key, result:SumStats::Result) =
{
return result["attack_discovery"]$sum;
},
$threshold_crossed(key:SumStats::Key, result:SumStats::Result) =
{
local s = fmt("Detected activity from host %s, total attempts %.0f within timeframe %s", key$host, result["attack_discovery"]$sum, bzar3_epoch);
# Raise Notice
NOTICE([$note=ATTACK::Discovery,
$msg=s]
);
}
]);
}
#end main.zeek