Merge remote-tracking branch 'origin/master' into topic/seth/metrics-merge

This commit is contained in:
Seth Hall 2012-11-16 02:49:36 -05:00
commit e99e090b85
112 changed files with 183377 additions and 712 deletions

View file

@ -1,4 +1,4 @@
##! Detect file downloads over HTTP that have MD5 sums matching files in Team
##! Detect file downloads over HTTP that have MD5 sums matching files in Team
##! Cymru's Malware Hash Registry (http://www.team-cymru.org/Services/MHR/).
##! By default, not all file transfers will have MD5 sums calculated. Read the
##! documentation for the :doc:base/protocols/http/file-hash.bro script to see
@ -10,11 +10,17 @@
module HTTP;
export {
redef enum Notice::Type += {
redef enum Notice::Type += {
## The MD5 sum of a file transferred over HTTP matched in the
## malware hash registry.
Malware_Hash_Registry_Match
};
## The malware hash registry runs each malware sample through several A/V engines.
## Team Cymru returns a percentage to indicate how many A/V engines flagged the
## sample as malicious. This threshold allows you to require a minimum detection
## rate (default: 50%).
const MHR_threshold = 50 &redef;
}
event log_http(rec: HTTP::Info)
@ -22,14 +28,15 @@ event log_http(rec: HTTP::Info)
if ( rec?$md5 )
{
local hash_domain = fmt("%s.malware.hash.cymru.com", rec$md5);
when ( local addrs = lookup_hostname(hash_domain) )
when ( local MHR_result = lookup_hostname_txt(hash_domain) )
{
# 127.0.0.2 indicates that the md5 sum was found in the MHR.
if ( 127.0.0.2 in addrs )
# Data is returned as "<dateFirstDetected> <detectionRate>"
local MHR_answer = split1(MHR_result, / /);
if ( length(MHR_answer) == 2 && to_count(MHR_answer[2]) >= MHR_threshold )
{
local url = HTTP::build_url_http(rec);
local message = fmt("%s %s %s", rec$id$orig_h, rec$md5, url);
NOTICE([$note=Malware_Hash_Registry_Match,
NOTICE([$note=Malware_Hash_Registry_Match,
$msg=message, $id=rec$id, $URL=url]);
}
}

View file

@ -1,21 +0,0 @@
##! Intelligence based HTTP detections. Not yet working!
@load base/protocols/http/main
@load base/protocols/http/utils
@load base/frameworks/intel/main
module HTTP;
event log_http(rec: Info)
{
local url = HTTP::build_url(rec);
local query = [$str=url, $subtype="url", $or_tags=set("malicious", "malware")];
if ( Intel::matcher(query) )
{
local msg = fmt("%s accessed a malicious URL from the intelligence framework", rec$id$orig_h);
NOTICE([$note=Intel::Detection,
$msg=msg,
$sub=HTTP::build_url_http(rec),
$id=rec$id]);
}
}

View file

@ -0,0 +1,58 @@
##! Script for tracking known Modbus masters and slaves.
##!
##! .. todo: This script needs a lot of work. What might be more interesting is to track
##! master/slave relationships based on commands sent and successful (non-exception)
##! responses.
@load base/protocols/modbus
module Known;
export {
redef enum Log::ID += { MODBUS_LOG };
type ModbusDeviceType: enum {
MODBUS_MASTER,
MODBUS_SLAVE,
};
type ModbusInfo: record {
## The time the device was discovered.
ts: time &log;
## The IP address of the host.
host: addr &log;
## The type of device being tracked.
device_type: ModbusDeviceType &log;
};
## The Modbus nodes being tracked.
global modbus_nodes: set[addr, ModbusDeviceType] &create_expire=1day &redef;
## Event that can be handled to access the loggable record as it is sent
## on to the logging framework.
global log_known_modbus: event(rec: ModbusInfo);
}
event bro_init() &priority=5
{
Log::create_stream(Known::MODBUS_LOG, [$columns=ModbusInfo, $ev=log_known_modbus]);
}
event modbus_message(c: connection, headers: ModbusHeaders, is_orig: bool)
{
local master = c$id$orig_h;
local slave = c$id$resp_h;
if ( [master, MODBUS_MASTER] !in modbus_nodes )
{
add modbus_nodes[master, MODBUS_MASTER];
Log::write(MODBUS_LOG, [$ts=network_time(), $host=master, $device_type=MODBUS_MASTER]);
}
if ( [slave, MODBUS_SLAVE] !in modbus_nodes )
{
add modbus_nodes[slave, MODBUS_SLAVE];
Log::write(MODBUS_LOG, [$ts=network_time(), $host=slave, $device_type=MODBUS_SLAVE]);
}
}

View file

@ -0,0 +1,104 @@
##! This script tracks the memory map of holding (read/write) registers and logs
##! changes as they are discovered.
##!
##! .. todo: Not all register reads and write functions are being supported yet.
module Modbus;
@load base/protocols/modbus
@load base/utils/directions-and-hosts
export {
redef enum Log::ID += { Modbus::REGISTER_CHANGE_LOG };
## The hosts that should have memory mapping enabled.
const track_memmap: Host = ALL_HOSTS &redef;
type MemmapInfo: record {
## Timestamp for the detected register change
ts: time &log;
## Unique ID for the connection
uid: string &log;
## Connection ID.
id: conn_id &log;
## The device memory offset.
register: count &log;
## The old value stored in the register.
old_val: count &log;
## The new value stored in the register.
new_val: count &log;
## The time delta between when the 'old_val' and 'new_val' were seen.
delta: interval &log;
};
type RegisterValue: record {
last_set: time;
value: count;
};
## Indexed on the device register value and yielding the register value.
type Registers: table[count] of RegisterValue;
## The memory map of slaves is tracked with this variable.
global device_registers: table[addr] of Registers;
## This event is generated every time a register is seen to be different than
## it was previously seen to be.
global changed_register: event(c: connection, register: count, old_val: count, new_val: count, delta: interval);
}
redef record Modbus::Info += {
track_address: count &default=0;
};
event bro_init() &priority=5
{
Log::create_stream(Modbus::REGISTER_CHANGE_LOG, [$columns=MemmapInfo]);
}
event modbus_read_holding_registers_request(c: connection, headers: ModbusHeaders, start_address: count, quantity: count)
{
c$modbus$track_address = start_address+1;
}
event modbus_read_holding_registers_response(c: connection, headers: ModbusHeaders, registers: ModbusRegisters)
{
local slave = c$id$resp_h;
if ( ! addr_matches_host(slave, track_memmap ) )
return;
if ( slave !in device_registers )
device_registers[slave] = table();
local slave_regs = device_registers[slave];
for ( i in registers )
{
if ( c$modbus$track_address in slave_regs )
{
if ( slave_regs[c$modbus$track_address]$value != registers[i] )
{
local delta = network_time() - slave_regs[c$modbus$track_address]$last_set;
event Modbus::changed_register(c, c$modbus$track_address,
slave_regs[c$modbus$track_address]$value, registers[i],
delta);
slave_regs[c$modbus$track_address]$last_set = network_time();
slave_regs[c$modbus$track_address]$value = registers[i];
}
}
else
{
local tmp_reg: RegisterValue = [$last_set=network_time(), $value=registers[i]];
slave_regs[c$modbus$track_address] = tmp_reg;
}
++c$modbus$track_address;
}
}
event Modbus::changed_register(c: connection, register: count, old_val: count, new_val: count, delta: interval)
{
local rec: MemmapInfo = [$ts=network_time(), $uid=c$uid, $id=c$id,
$register=register, $old_val=old_val, $new_val=new_val, $delta=delta];
Log::write(REGISTER_CHANGE_LOG, rec);
}