mirror of
https://github.com/zeek/zeek.git
synced 2025-10-14 12:38:20 +00:00
Merge remote-tracking branch 'origin/master' into topic/bernhard/thread-cleanup
This commit is contained in:
commit
2cc1f82425
37 changed files with 854 additions and 74 deletions
|
@ -29,6 +29,8 @@ export {
|
|||
minor: count &optional;
|
||||
## Minor subversion number
|
||||
minor2: count &optional;
|
||||
## Minor updates number
|
||||
minor3: count &optional;
|
||||
## Additional version string (e.g. "beta42")
|
||||
addl: string &optional;
|
||||
} &log;
|
||||
|
@ -146,10 +148,10 @@ function parse(unparsed_version: string): Description
|
|||
if ( /^[\/\-\._v\(]/ in sv )
|
||||
sv = strip(sub(version_parts[2], /^\(?[\/\-\._v\(]/, ""));
|
||||
local version_numbers = split_n(sv, /[\-\._,\[\(\{ ]/, F, 3);
|
||||
if ( 4 in version_numbers && version_numbers[4] != "" )
|
||||
v$addl = strip(version_numbers[4]);
|
||||
if ( 5 in version_numbers && version_numbers[5] != "" )
|
||||
v$addl = strip(version_numbers[5]);
|
||||
else if ( 3 in version_parts && version_parts[3] != "" &&
|
||||
version_parts[3] != ")" )
|
||||
version_parts[3] != ")" )
|
||||
{
|
||||
if ( /^[[:blank:]]*\([a-zA-Z0-9\-\._[:blank:]]*\)/ in version_parts[3] )
|
||||
{
|
||||
|
@ -177,7 +179,9 @@ function parse(unparsed_version: string): Description
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ( 4 in version_numbers && version_numbers[4] != "" )
|
||||
v$minor3 = extract_count(version_numbers[4]);
|
||||
if ( 3 in version_numbers && version_numbers[3] != "" )
|
||||
v$minor2 = extract_count(version_numbers[3]);
|
||||
if ( 2 in version_numbers && version_numbers[2] != "" )
|
||||
|
@ -332,8 +336,25 @@ function cmp_versions(v1: Version, v2: Version): int
|
|||
return v1?$minor2 ? 1 : -1;
|
||||
}
|
||||
|
||||
if ( v1?$minor3 && v2?$minor3 )
|
||||
{
|
||||
if ( v1$minor3 < v2$minor3 )
|
||||
return -1;
|
||||
if ( v1$minor3 > v2$minor3 )
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !v1?$minor3 && !v2?$minor3 )
|
||||
{ }
|
||||
else
|
||||
return v1?$minor3 ? 1 : -1;
|
||||
}
|
||||
|
||||
if ( v1?$addl && v2?$addl )
|
||||
{
|
||||
return strcmp(v1$addl, v2$addl);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !v1?$addl && !v2?$addl )
|
||||
|
@ -341,6 +362,9 @@ function cmp_versions(v1: Version, v2: Version): int
|
|||
else
|
||||
return v1?$addl ? 1 : -1;
|
||||
}
|
||||
|
||||
# A catcher return that should never be reached...hopefully
|
||||
return 0;
|
||||
}
|
||||
|
||||
function software_endpoint_name(id: conn_id, host: addr): string
|
||||
|
@ -351,10 +375,11 @@ function software_endpoint_name(id: conn_id, host: addr): string
|
|||
# Convert a version into a string "a.b.c-x".
|
||||
function software_fmt_version(v: Version): string
|
||||
{
|
||||
return fmt("%d.%d.%d%s",
|
||||
v?$major ? v$major : 0,
|
||||
v?$minor ? v$minor : 0,
|
||||
v?$minor2 ? v$minor2 : 0,
|
||||
return fmt("%s%s%s%s%s",
|
||||
v?$major ? fmt("%d", v$major) : "0",
|
||||
v?$minor ? fmt(".%d", v$minor) : "",
|
||||
v?$minor2 ? fmt(".%d", v$minor2) : "",
|
||||
v?$minor3 ? fmt(".%d", v$minor3) : "",
|
||||
v?$addl ? fmt("-%s", v$addl) : "");
|
||||
}
|
||||
|
||||
|
|
|
@ -67,11 +67,6 @@ export {
|
|||
## (especially with large file transfers).
|
||||
const disable_analyzer_after_detection = T &redef;
|
||||
|
||||
## The openssl command line utility. If it's in the path the default
|
||||
## value will work, otherwise a full path string can be supplied for the
|
||||
## utility.
|
||||
const openssl_util = "openssl" &redef;
|
||||
|
||||
## The maximum amount of time a script can delay records from being logged.
|
||||
const max_log_delay = 15secs &redef;
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
##! Provides a variable to define vulnerable versions of software and if a
|
||||
##! a version of that software as old or older than the defined version a
|
||||
##! Provides a variable to define vulnerable versions of software and if a
|
||||
##! a version of that software as old or older than the defined version a
|
||||
##! notice will be generated.
|
||||
|
||||
@load base/frameworks/control
|
||||
@load base/frameworks/notice
|
||||
@load base/frameworks/software
|
||||
|
||||
|
@ -13,17 +14,126 @@ export {
|
|||
Vulnerable_Version,
|
||||
};
|
||||
|
||||
## This is a table of software versions indexed by the name of the
|
||||
## software and yielding the latest version that is vulnerable.
|
||||
const vulnerable_versions: table[string] of Version &redef;
|
||||
type VulnerableVersionRange: record {
|
||||
## The minimal version of a vulnerable version range. This
|
||||
## field can be undefined if all previous versions of a piece
|
||||
## of software are vulnerable.
|
||||
min: Software::Version &optional;
|
||||
## The maximum vulnerable version. This field is deliberately
|
||||
## not optional because a maximum vulnerable version must
|
||||
## always be defined. This assumption may become incorrent
|
||||
## if all future versions of some software are to be considered
|
||||
## vulnerable. :)
|
||||
max: Software::Version;
|
||||
};
|
||||
|
||||
## The DNS zone where runtime vulnerable software updates will
|
||||
## be loaded from.
|
||||
const vulnerable_versions_update_endpoint = "" &redef;
|
||||
|
||||
## The interval at which vulnerable versions should grab updates
|
||||
## over DNS.
|
||||
const vulnerable_versions_update_interval = 1hr &redef;
|
||||
|
||||
## This is a table of software versions indexed by the name of the
|
||||
## software and a set of version ranges that are declared to be
|
||||
## vulnerable for that software.
|
||||
const vulnerable_versions: table[string] of set[VulnerableVersionRange] = table() &redef;
|
||||
}
|
||||
|
||||
global internal_vulnerable_versions: table[string] of set[VulnerableVersionRange] = table();
|
||||
|
||||
event Control::configuration_update()
|
||||
{
|
||||
internal_vulnerable_versions = table();
|
||||
|
||||
# Copy the const vulnerable versions into the global modifiable one.
|
||||
for ( sw in vulnerable_versions )
|
||||
internal_vulnerable_versions[sw] = vulnerable_versions[sw];
|
||||
}
|
||||
|
||||
function decode_vulnerable_version_range(vuln_sw: string): VulnerableVersionRange
|
||||
{
|
||||
# Create a max value with a dunce value only because the $max field
|
||||
# is not optional.
|
||||
local vvr: Software::VulnerableVersionRange = [$max=[$major=0]];
|
||||
|
||||
if ( /max=/ !in vuln_sw )
|
||||
{
|
||||
Reporter::warning(fmt("The vulnerable software detection script encountered a version with no max value (which is required). %s", vuln_sw));
|
||||
return vvr;
|
||||
}
|
||||
|
||||
local versions = split1(vuln_sw, /\x09/);
|
||||
|
||||
for ( i in versions )
|
||||
{
|
||||
local field_and_ver = split1(versions[i], /=/);
|
||||
if ( |field_and_ver| != 2 )
|
||||
return vvr; #failure!
|
||||
|
||||
local ver = Software::parse(field_and_ver[2])$version;
|
||||
if ( field_and_ver[1] == "min" )
|
||||
vvr$min = ver;
|
||||
else if ( field_and_ver[1] == "max" )
|
||||
vvr$max = ver;
|
||||
}
|
||||
|
||||
return vvr;
|
||||
}
|
||||
|
||||
event grab_vulnerable_versions(i: count)
|
||||
{
|
||||
if ( vulnerable_versions_update_endpoint == "" )
|
||||
{
|
||||
# Reschedule this event in case the user updates the setting at runtime.
|
||||
schedule vulnerable_versions_update_interval { grab_vulnerable_versions(1) };
|
||||
return;
|
||||
}
|
||||
|
||||
when ( local result = lookup_hostname_txt(cat(i,".",vulnerable_versions_update_endpoint)) )
|
||||
{
|
||||
local parts = split1(result, /\x09/);
|
||||
if ( |parts| != 2 ) #failure or end of list!
|
||||
{
|
||||
schedule vulnerable_versions_update_interval { grab_vulnerable_versions(1) };
|
||||
return;
|
||||
}
|
||||
|
||||
local sw = parts[1];
|
||||
local vvr = decode_vulnerable_version_range(parts[2]);
|
||||
if ( sw !in internal_vulnerable_versions )
|
||||
internal_vulnerable_versions[sw] = set();
|
||||
add internal_vulnerable_versions[sw][vvr];
|
||||
|
||||
event grab_vulnerable_versions(i+1);
|
||||
}
|
||||
timeout 5secs
|
||||
{
|
||||
# In case a lookup fails, try starting over in one minute.
|
||||
schedule 1min { grab_vulnerable_versions(1) };
|
||||
}
|
||||
}
|
||||
|
||||
event bro_init()
|
||||
{
|
||||
event grab_vulnerable_versions(1);
|
||||
}
|
||||
|
||||
event log_software(rec: Info)
|
||||
{
|
||||
if ( rec$name in vulnerable_versions &&
|
||||
cmp_versions(rec$version, vulnerable_versions[rec$name]) <= 0 )
|
||||
if ( rec$name !in internal_vulnerable_versions )
|
||||
return;
|
||||
|
||||
for ( version_range in internal_vulnerable_versions[rec$name] )
|
||||
{
|
||||
NOTICE([$note=Vulnerable_Version, $src=rec$host,
|
||||
$msg=fmt("A vulnerable version of software was detected: %s", software_fmt(rec))]);
|
||||
if ( cmp_versions(rec$version, version_range$max) <= 0 &&
|
||||
(!version_range?$min || cmp_versions(rec$version, version_range$min) >= 0) )
|
||||
{
|
||||
# The software is inside a vulnerable version range.
|
||||
NOTICE([$note=Vulnerable_Version, $src=rec$host,
|
||||
$msg=fmt("%s is running %s which is vulnerable.", rec$host, software_fmt(rec)),
|
||||
$sub=software_fmt(rec)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,14 +4,10 @@
|
|||
##!
|
||||
##! ..note::
|
||||
##!
|
||||
##! - It doesn't work well on a cluster because each worker will write its
|
||||
##! - It doesn't work well on a cluster because each worker will write its
|
||||
##! own certificate files and no duplicate checking is done across
|
||||
##! clusters so each node would log each certificate.
|
||||
##!
|
||||
##! - If there is a certificate input based vulnerability found in the
|
||||
##! openssl command line utility, you could be in trouble because this
|
||||
##! script uses that utility to convert from DER to PEM certificates.
|
||||
##!
|
||||
|
||||
@load base/protocols/ssl
|
||||
@load base/utils/directions-and-hosts
|
||||
|
@ -20,7 +16,7 @@
|
|||
module SSL;
|
||||
|
||||
export {
|
||||
## Control if host certificates offered by the defined hosts
|
||||
## Control if host certificates offered by the defined hosts
|
||||
## will be written to the PEM certificates file.
|
||||
## Choices are: LOCAL_HOSTS, REMOTE_HOSTS, ALL_HOSTS, NO_HOSTS
|
||||
const extract_certs_pem = LOCAL_HOSTS &redef;
|
||||
|
@ -35,15 +31,33 @@ event ssl_established(c: connection) &priority=5
|
|||
{
|
||||
if ( ! c$ssl?$cert )
|
||||
return;
|
||||
|
||||
if ( ! addr_matches_host(c$id$resp_h, extract_certs_pem) )
|
||||
return;
|
||||
|
||||
|
||||
if ( c$ssl$cert_hash in extracted_certs )
|
||||
# If we already extracted this cert, don't do it again.
|
||||
return;
|
||||
|
||||
|
||||
add extracted_certs[c$ssl$cert_hash];
|
||||
local side = Site::is_local_addr(c$id$resp_h) ? "local" : "remote";
|
||||
local cmd = fmt("%s x509 -inform DER -outform PEM >> certs-%s.pem", openssl_util, side);
|
||||
piped_exec(cmd, c$ssl$cert);
|
||||
local filename = Site::is_local_addr(c$id$resp_h) ? "certs-local.pem" : "certs-remote.pem";
|
||||
local outfile = open_for_append(filename);
|
||||
|
||||
print outfile, "-----BEGIN CERTIFICATE-----";
|
||||
|
||||
# Encode to base64 and format to fit 50 lines. Otherwise openssl won't like it later.
|
||||
local lines = split_all(encode_base64(c$ssl$cert), /.{50}/);
|
||||
local i = 1;
|
||||
for ( line in lines )
|
||||
{
|
||||
if ( |lines[i]| > 0 )
|
||||
{
|
||||
print outfile, lines[i];
|
||||
}
|
||||
i+=1;
|
||||
}
|
||||
|
||||
print outfile, "-----END CERTIFICATE-----";
|
||||
print outfile, "";
|
||||
close(outfile);
|
||||
}
|
||||
|
|
|
@ -14,13 +14,6 @@
|
|||
# information.
|
||||
@load frameworks/software/vulnerable
|
||||
|
||||
# Example vulnerable software. This needs to be updated and maintained over
|
||||
# time as new vulnerabilities are discovered.
|
||||
redef Software::vulnerable_versions += {
|
||||
["Flash"] = [$major=10,$minor=2,$minor2=153,$addl="1"],
|
||||
["Java"] = [$major=1,$minor=6,$minor2=0,$addl="22"],
|
||||
};
|
||||
|
||||
# Detect software changing (e.g. attacker installing hacked SSHD).
|
||||
@load frameworks/software/version-changes
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue