mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 06:38:20 +00:00
Merge remote-tracking branch 'origin/topic/bernhard/software'
* origin/topic/bernhard/software: change software framework interface again. At the moment everything should worl. start reworking interface of software framework. working apart from detect-webapps.bro, which direcly manipulates a no longer available interface... after talking to seth - change host_a field in record back to host. forgotten policy files. Software framework stores ports for server software.
This commit is contained in:
commit
2cd88ee4f6
8 changed files with 203 additions and 196 deletions
|
@ -36,15 +36,17 @@ export {
|
|||
## The record type that is used for representing and logging software.
|
||||
type Info: record {
|
||||
## The time at which the software was detected.
|
||||
ts: time &log;
|
||||
ts: time &log &optional;
|
||||
## The IP address detected running the software.
|
||||
host: addr &log;
|
||||
## The Port on which the software is running. Only sensible for server software.
|
||||
host_p: port &log &optional;
|
||||
## The type of software detected (e.g. :bro:enum:`HTTP::SERVER`).
|
||||
software_type: Type &log &default=UNKNOWN;
|
||||
## Name of the software (e.g. Apache).
|
||||
name: string &log;
|
||||
name: string &log &optional;
|
||||
## Version of the software.
|
||||
version: Version &log;
|
||||
version: Version &log &optional;
|
||||
## The full unparsed version string found because the version parsing
|
||||
## doesn't always work reliably in all cases and this acts as a
|
||||
## fallback in the logs.
|
||||
|
@ -65,31 +67,12 @@ export {
|
|||
const asset_tracking = LOCAL_HOSTS &redef;
|
||||
|
||||
## Other scripts should call this function when they detect software.
|
||||
## unparsed_version: This is the full string from which the
|
||||
## :bro:type:`Software::Info` was extracted.
|
||||
##
|
||||
## id: The connection id where the software was discovered.
|
||||
##
|
||||
## info: A record representing the software discovered.
|
||||
##
|
||||
## Returns: T if the software was logged, F otherwise.
|
||||
global found: function(id: conn_id, info: Software::Info): bool;
|
||||
|
||||
## Take many common software version strings and parse them
|
||||
## into a sensible :bro:type:`Software::Version` record. There are
|
||||
## still many cases where scripts may have to have their own specific
|
||||
## version parsing though.
|
||||
##
|
||||
## unparsed_version: The raw version string.
|
||||
##
|
||||
## host: The host where the software was discovered.
|
||||
##
|
||||
## software_type: The type of software.
|
||||
##
|
||||
## Returns: A complete record ready for the :bro:id:`Software::found` function.
|
||||
global parse: function(unparsed_version: string,
|
||||
host: addr,
|
||||
software_type: Type): Info;
|
||||
global found: function(id: conn_id, info: Info): bool;
|
||||
|
||||
## Compare two version records.
|
||||
##
|
||||
|
@ -117,112 +100,23 @@ export {
|
|||
global log_software: event(rec: Info);
|
||||
}
|
||||
|
||||
event bro_init()
|
||||
event bro_init() &priority=5
|
||||
{
|
||||
Log::create_stream(Software::LOG, [$columns=Info, $ev=log_software]);
|
||||
}
|
||||
|
||||
function parse_mozilla(unparsed_version: string,
|
||||
host: addr,
|
||||
software_type: Type): Info
|
||||
{
|
||||
local software_name = "<unknown browser>";
|
||||
local v: Version;
|
||||
local parts: table[count] of string;
|
||||
|
||||
if ( /Opera [0-9\.]*$/ in unparsed_version )
|
||||
{
|
||||
software_name = "Opera";
|
||||
parts = split_all(unparsed_version, /Opera [0-9\.]*$/);
|
||||
if ( 2 in parts )
|
||||
v = parse(parts[2], host, software_type)$version;
|
||||
}
|
||||
else if ( / MSIE / in unparsed_version )
|
||||
{
|
||||
software_name = "MSIE";
|
||||
if ( /Trident\/4\.0/ in unparsed_version )
|
||||
v = [$major=8,$minor=0];
|
||||
else if ( /Trident\/5\.0/ in unparsed_version )
|
||||
v = [$major=9,$minor=0];
|
||||
else if ( /Trident\/6\.0/ in unparsed_version )
|
||||
v = [$major=10,$minor=0];
|
||||
else
|
||||
{
|
||||
parts = split_all(unparsed_version, /MSIE [0-9]{1,2}\.*[0-9]*b?[0-9]*/);
|
||||
if ( 2 in parts )
|
||||
v = parse(parts[2], host, software_type)$version;
|
||||
}
|
||||
}
|
||||
else if ( /Version\/.*Safari\// in unparsed_version )
|
||||
{
|
||||
software_name = "Safari";
|
||||
parts = split_all(unparsed_version, /Version\/[0-9\.]*/);
|
||||
if ( 2 in parts )
|
||||
{
|
||||
v = parse(parts[2], host, software_type)$version;
|
||||
if ( / Mobile\/?.* Safari/ in unparsed_version )
|
||||
v$addl = "Mobile";
|
||||
}
|
||||
}
|
||||
else if ( /(Firefox|Netscape|Thunderbird)\/[0-9\.]*/ in unparsed_version )
|
||||
{
|
||||
parts = split_all(unparsed_version, /(Firefox|Netscape|Thunderbird)\/[0-9\.]*/);
|
||||
if ( 2 in parts )
|
||||
{
|
||||
local tmp_s = parse(parts[2], host, software_type);
|
||||
software_name = tmp_s$name;
|
||||
v = tmp_s$version;
|
||||
}
|
||||
}
|
||||
else if ( /Chrome\/.*Safari\// in unparsed_version )
|
||||
{
|
||||
software_name = "Chrome";
|
||||
parts = split_all(unparsed_version, /Chrome\/[0-9\.]*/);
|
||||
if ( 2 in parts )
|
||||
v = parse(parts[2], host, software_type)$version;
|
||||
}
|
||||
else if ( /^Opera\// in unparsed_version )
|
||||
{
|
||||
if ( /Opera M(ini|obi)\// in unparsed_version )
|
||||
{
|
||||
parts = split_all(unparsed_version, /Opera M(ini|obi)/);
|
||||
if ( 2 in parts )
|
||||
software_name = parts[2];
|
||||
parts = split_all(unparsed_version, /Version\/[0-9\.]*/);
|
||||
if ( 2 in parts )
|
||||
v = parse(parts[2], host, software_type)$version;
|
||||
else
|
||||
{
|
||||
parts = split_all(unparsed_version, /Opera Mini\/[0-9\.]*/);
|
||||
if ( 2 in parts )
|
||||
v = parse(parts[2], host, software_type)$version;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
software_name = "Opera";
|
||||
parts = split_all(unparsed_version, /Version\/[0-9\.]*/);
|
||||
if ( 2 in parts )
|
||||
v = parse(parts[2], host, software_type)$version;
|
||||
}
|
||||
}
|
||||
else if ( /AppleWebKit\/[0-9\.]*/ in unparsed_version )
|
||||
{
|
||||
software_name = "Unspecified WebKit";
|
||||
parts = split_all(unparsed_version, /AppleWebKit\/[0-9\.]*/);
|
||||
if ( 2 in parts )
|
||||
v = parse(parts[2], host, software_type)$version;
|
||||
}
|
||||
type Description: record {
|
||||
name: string;
|
||||
version: Version;
|
||||
unparsed_version: string;
|
||||
};
|
||||
|
||||
return [$ts=network_time(), $host=host, $name=software_name, $version=v,
|
||||
$software_type=software_type, $unparsed_version=unparsed_version];
|
||||
}
|
||||
# Defining this here because of a circular dependency between two functions.
|
||||
global parse_mozilla: function(unparsed_version: string): Description;
|
||||
|
||||
# Don't even try to understand this now, just make sure the tests are
|
||||
# working.
|
||||
function parse(unparsed_version: string,
|
||||
host: addr,
|
||||
software_type: Type): Info
|
||||
function parse(unparsed_version: string): Description
|
||||
{
|
||||
local software_name = "<parse error>";
|
||||
local v: Version;
|
||||
|
@ -230,7 +124,7 @@ function parse(unparsed_version: string,
|
|||
# Parse browser-alike versions separately
|
||||
if ( /^(Mozilla|Opera)\/[0-9]\./ in unparsed_version )
|
||||
{
|
||||
return parse_mozilla(unparsed_version, host, software_type);
|
||||
return parse_mozilla(unparsed_version);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -255,7 +149,7 @@ function parse(unparsed_version: string,
|
|||
if ( 4 in version_numbers && version_numbers[4] != "" )
|
||||
v$addl = strip(version_numbers[4]);
|
||||
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] )
|
||||
{
|
||||
|
@ -292,9 +186,102 @@ function parse(unparsed_version: string,
|
|||
v$major = extract_count(version_numbers[1]);
|
||||
}
|
||||
}
|
||||
return [$ts=network_time(), $host=host, $name=software_name,
|
||||
$version=v, $unparsed_version=unparsed_version,
|
||||
$software_type=software_type];
|
||||
|
||||
return [$version=v, $unparsed_version=unparsed_version, $name=software_name];
|
||||
}
|
||||
|
||||
|
||||
function parse_mozilla(unparsed_version: string): Description
|
||||
{
|
||||
local software_name = "<unknown browser>";
|
||||
local v: Version;
|
||||
local parts: table[count] of string;
|
||||
|
||||
if ( /Opera [0-9\.]*$/ in unparsed_version )
|
||||
{
|
||||
software_name = "Opera";
|
||||
parts = split_all(unparsed_version, /Opera [0-9\.]*$/);
|
||||
if ( 2 in parts )
|
||||
v = parse(parts[2])$version;
|
||||
}
|
||||
else if ( / MSIE / in unparsed_version )
|
||||
{
|
||||
software_name = "MSIE";
|
||||
if ( /Trident\/4\.0/ in unparsed_version )
|
||||
v = [$major=8,$minor=0];
|
||||
else if ( /Trident\/5\.0/ in unparsed_version )
|
||||
v = [$major=9,$minor=0];
|
||||
else if ( /Trident\/6\.0/ in unparsed_version )
|
||||
v = [$major=10,$minor=0];
|
||||
else
|
||||
{
|
||||
parts = split_all(unparsed_version, /MSIE [0-9]{1,2}\.*[0-9]*b?[0-9]*/);
|
||||
if ( 2 in parts )
|
||||
v = parse(parts[2])$version;
|
||||
}
|
||||
}
|
||||
else if ( /Version\/.*Safari\// in unparsed_version )
|
||||
{
|
||||
software_name = "Safari";
|
||||
parts = split_all(unparsed_version, /Version\/[0-9\.]*/);
|
||||
if ( 2 in parts )
|
||||
{
|
||||
v = parse(parts[2])$version;
|
||||
if ( / Mobile\/?.* Safari/ in unparsed_version )
|
||||
v$addl = "Mobile";
|
||||
}
|
||||
}
|
||||
else if ( /(Firefox|Netscape|Thunderbird)\/[0-9\.]*/ in unparsed_version )
|
||||
{
|
||||
parts = split_all(unparsed_version, /(Firefox|Netscape|Thunderbird)\/[0-9\.]*/);
|
||||
if ( 2 in parts )
|
||||
{
|
||||
local tmp_s = parse(parts[2]);
|
||||
software_name = tmp_s$name;
|
||||
v = tmp_s$version;
|
||||
}
|
||||
}
|
||||
else if ( /Chrome\/.*Safari\// in unparsed_version )
|
||||
{
|
||||
software_name = "Chrome";
|
||||
parts = split_all(unparsed_version, /Chrome\/[0-9\.]*/);
|
||||
if ( 2 in parts )
|
||||
v = parse(parts[2])$version;
|
||||
}
|
||||
else if ( /^Opera\// in unparsed_version )
|
||||
{
|
||||
if ( /Opera M(ini|obi)\// in unparsed_version )
|
||||
{
|
||||
parts = split_all(unparsed_version, /Opera M(ini|obi)/);
|
||||
if ( 2 in parts )
|
||||
software_name = parts[2];
|
||||
parts = split_all(unparsed_version, /Version\/[0-9\.]*/);
|
||||
if ( 2 in parts )
|
||||
v = parse(parts[2])$version;
|
||||
else
|
||||
{
|
||||
parts = split_all(unparsed_version, /Opera Mini\/[0-9\.]*/);
|
||||
if ( 2 in parts )
|
||||
v = parse(parts[2])$version;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
software_name = "Opera";
|
||||
parts = split_all(unparsed_version, /Version\/[0-9\.]*/);
|
||||
if ( 2 in parts )
|
||||
v = parse(parts[2])$version;
|
||||
}
|
||||
}
|
||||
else if ( /AppleWebKit\/[0-9\.]*/ in unparsed_version )
|
||||
{
|
||||
software_name = "Unspecified WebKit";
|
||||
parts = split_all(unparsed_version, /AppleWebKit\/[0-9\.]*/);
|
||||
if ( 2 in parts )
|
||||
v = parse(parts[2])$version;
|
||||
}
|
||||
|
||||
return [$version=v, $unparsed_version=unparsed_version, $name=software_name];
|
||||
}
|
||||
|
||||
|
||||
|
@ -407,6 +394,30 @@ function found(id: conn_id, info: Info): bool
|
|||
{
|
||||
if ( info$force_log || addr_matches_host(info$host, asset_tracking) )
|
||||
{
|
||||
if ( !info?$ts )
|
||||
info$ts=network_time();
|
||||
|
||||
if ( info?$version ) # we have a version number and don't have to parse. check if the name is also set...
|
||||
{
|
||||
if ( ! info?$name )
|
||||
{
|
||||
Reporter::error("Required field name not present in Software::found");
|
||||
return F;
|
||||
}
|
||||
}
|
||||
else # no version present, we have to parse...
|
||||
{
|
||||
if ( !info?$unparsed_version )
|
||||
{
|
||||
Reporter::error("No unparsed version string present in Info record with version in Software::found");
|
||||
return F;
|
||||
}
|
||||
local sw = parse(info$unparsed_version);
|
||||
info$unparsed_version = sw$unparsed_version;
|
||||
info$name = sw$name;
|
||||
info$version = sw$version;
|
||||
}
|
||||
|
||||
event software_register(id, info);
|
||||
return T;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue