From: Masud Hasan (mashasan) Date: Wed, 28 Oct 2020 00:00:27 +0000 (+0000) Subject: Merge pull request #2580 in SNORT/snort3 from ~ARMANDAV/snort3:rna_banner to master X-Git-Tag: 3.0.3-5~31 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=64829f460fd397d24e8b96806028a639948ca897;p=thirdparty%2Fsnort3.git Merge pull request #2580 in SNORT/snort3 from ~ARMANDAV/snort3:rna_banner to master Squashed commit of the following: commit ce08354fcfaf79ee973c489c1ad439fa34657fe5 Author: Arun Mandava Date: Thu Oct 15 20:58:37 2020 -0400 rna: Support banner discovery --- diff --git a/src/host_tracker/host_tracker.cc b/src/host_tracker/host_tracker.cc index e04707e11..2e9e9d97a 100644 --- a/src/host_tracker/host_tracker.cc +++ b/src/host_tracker/host_tracker.cc @@ -308,6 +308,7 @@ void HostTracker::clear_service(HostApplication& ha) ha.last_seen = 0; ha.payloads.clear(); ha.info.clear(); + ha.banner_updated = false; } bool HostTracker::add_client_payload(HostClient& hc, AppId payload, size_t max_payloads) @@ -592,6 +593,24 @@ bool HostTracker::update_service_info(HostApplication& ha, const char* vendor, return false; } +bool HostTracker::update_service_banner(Port port, IpProtocol proto) +{ + host_tracker_stats.service_finds++; + lock_guard lck(host_tracker_lock); + for ( auto& s : services ) + { + if ( s.port == port and s.proto == proto ) + { + if ( !s.visibility or s.banner_updated ) + return false; + + s.banner_updated = true; + return true; + } + } + return false; +} + bool HostTracker::update_service_user(Port port, IpProtocol proto, const char* user) { host_tracker_stats.service_finds++; @@ -718,6 +737,7 @@ bool HostTracker::set_service_visibility(Port port, IpProtocol proto, bool v) for ( auto& info : s.info ) info.visibility = false; s.user[0] = '\0'; + s.banner_updated = false; } return true; } diff --git a/src/host_tracker/host_tracker.h b/src/host_tracker/host_tracker.h index 040761fcd..819b2bdc8 100644 --- a/src/host_tracker/host_tracker.h +++ b/src/host_tracker/host_tracker.h @@ -86,8 +86,9 @@ typedef AppId Payload_t; struct HostApplication { HostApplication() = default; - HostApplication(Port pt, IpProtocol pr, AppId ap, bool in, uint32_t ht = 0, uint32_t ls = 0) : - port(pt), proto(pr), appid(ap), inferred_appid(in), hits(ht), last_seen(ls) { } + HostApplication(Port pt, IpProtocol pr, AppId ap, bool in, uint32_t ht = 0, uint32_t ls = 0, + bool banner = false) : port(pt), proto(pr), appid(ap), inferred_appid(in), hits(ht), + last_seen(ls), banner_updated(banner) { } HostApplication(const HostApplication& ha): port(ha.port), proto(ha.proto), appid(ha.appid), inferred_appid(ha.inferred_appid), hits(ha.hits), last_seen(ha.last_seen), info(ha.info), payloads(ha.payloads) { } @@ -102,6 +103,7 @@ struct HostApplication info = ha.info; payloads = ha.payloads; visibility = ha.visibility; + banner_updated = ha.banner_updated; return *this; } @@ -112,6 +114,7 @@ struct HostApplication uint32_t hits = 0; uint32_t last_seen = 0; char user[INFO_SIZE] = { '\0' }; + bool banner_updated = false; std::vector info; std::vector> payloads; @@ -292,6 +295,7 @@ public: void update_service(const HostApplication&); bool update_service_info(HostApplication&, const char* vendor, const char* version, uint16_t max_info); + bool update_service_banner(Port, IpProtocol); bool update_service_user(Port, IpProtocol, const char* username); void remove_inferred_services(); diff --git a/src/network_inspectors/rna/rna_app_discovery.cc b/src/network_inspectors/rna/rna_app_discovery.cc index c83995aa1..785c949bd 100644 --- a/src/network_inspectors/rna/rna_app_discovery.cc +++ b/src/network_inspectors/rna/rna_app_discovery.cc @@ -64,7 +64,8 @@ void RnaAppDiscovery::process(AppidEvent* appid_event, DiscoveryFilter& filter, const auto& appid_session_api = appid_event->get_appid_session_api(); if ( appid_change_bits[APPID_SERVICE_BIT] or appid_change_bits[APPID_CLIENT_BIT] or - appid_change_bits[APPID_PAYLOAD_BIT] ) + appid_change_bits[APPID_PAYLOAD_BIT] or appid_change_bits[APPID_SERVICE_VENDOR_BIT] or + appid_change_bits[APPID_VERSION_BIT] ) { AppId service, client, payload; appid_session_api.get_app_id(&service, &client, &payload, nullptr, nullptr); @@ -96,25 +97,24 @@ void RnaAppDiscovery::process(AppidEvent* appid_event, DiscoveryFilter& filter, src_mac, conf, logger, version, client, service); } - if ( appid_change_bits[APPID_PAYLOAD_BIT] and payload > APP_ID_NONE and - service > APP_ID_NONE) + if ( appid_change_bits[APPID_SERVICE_VENDOR_BIT] or appid_change_bits[APPID_VERSION_BIT] ) { - discover_payload(p, proto, ht, (const struct in6_addr*) src_ip->get_ip6_ptr(), - src_mac, conf, logger, service, payload, client); + const char* vendor; + const char* version; + const AppIdServiceSubtype* subtype; + appid_session_api.get_service_info(vendor, version, subtype); + update_service_info(p, proto, vendor, version, ht, src_ip, src_mac, logger, conf, + service); } - } - - if ( appid_change_bits[APPID_SERVICE_VENDOR_BIT] or appid_change_bits[APPID_VERSION_BIT] ) - { - const char* vendor; - const char* version; - const AppIdServiceSubtype* subtype; - AppId service, client, payload; - appid_session_api.get_app_id(&service, &client, &payload, nullptr, nullptr); - appid_session_api.get_service_info(vendor, version, subtype); - update_service_info(p, proto, vendor, version, ht, src_ip, src_mac, logger, conf, - service); + if ( appid_change_bits[APPID_PAYLOAD_BIT] and payload > APP_ID_NONE + and service > APP_ID_NONE ) + { + discover_payload(p, proto, ht, (const struct in6_addr*) src_ip->get_ip6_ptr(), + src_mac, conf, logger, service, payload, client); + if ( conf->enable_banner_grab ) + discover_banner(p, proto, ht, &p->flow->server_ip, src_mac, logger, service); + } } // Appid supports only login success event. Change checks once login failure and @@ -250,6 +250,33 @@ void RnaAppDiscovery::update_service_info(const Packet* p, IpProtocol proto, con rt->update_service(ha); } +void RnaAppDiscovery::discover_banner(const Packet* p, IpProtocol proto, RnaTracker& rt, + const snort::SfIp* ip, const uint8_t* mac, RnaLogger& logger, AppId service) +{ + auto srt = rt; + const uint8_t* service_mac = mac; + + HostApplication ha(p->flow->server_port, proto, service, false); + if ( p->is_from_client() ) + { + srt = host_cache.find(p->flow->server_ip); + if ( !srt ) + return; + + if ( layer::get_eth_layer(p) ) + service_mac = layer::get_eth_layer(p)->ether_dst; + else + service_mac = srt->get_last_seen_mac(); + } + + if ( !srt->update_service_banner(p->flow->server_port, proto) ) + return; + + ha.last_seen = (uint32_t) packet_time(); + logger.log(RNA_EVENT_CHANGE, CHANGE_BANNER_UPDATE, p, &srt, + (const struct in6_addr*) ip->get_ip6_ptr(), service_mac, &ha); +} + void RnaAppDiscovery::discover_client(const Packet* p, RnaTracker& rt, const struct in6_addr* src_ip, const uint8_t* src_mac, RnaConfig* conf, RnaLogger& logger, const char* version, AppId client, AppId service) diff --git a/src/network_inspectors/rna/rna_app_discovery.h b/src/network_inspectors/rna/rna_app_discovery.h index c647404c7..1a9856b75 100644 --- a/src/network_inspectors/rna/rna_app_discovery.h +++ b/src/network_inspectors/rna/rna_app_discovery.h @@ -43,6 +43,8 @@ public: static void discover_user(const snort::Packet*, RnaTracker&, const struct in6_addr*, RnaLogger&, const char* username, AppId, IpProtocol); + static void discover_banner(const snort::Packet*, IpProtocol, RnaTracker&, + const snort::SfIp*, const uint8_t* mac, RnaLogger&, AppId); private: static void update_service_info(const snort::Packet*, IpProtocol, const char* vendor, const char* version, RnaTracker&, const snort::SfIp*, const uint8_t*, diff --git a/src/network_inspectors/rna/rna_logger.cc b/src/network_inspectors/rna/rna_logger.cc index acabff94e..21479ba79 100644 --- a/src/network_inspectors/rna/rna_logger.cc +++ b/src/network_inspectors/rna/rna_logger.cc @@ -91,6 +91,8 @@ static inline void rna_logger_message(const RnaLoggerEvent& rle) debug_logf(rna_trace, nullptr, "RNA Service Info log: version: %s\n", s.version); } + if ( rle.type == RNA_EVENT_CHANGE and rle.subtype == CHANGE_BANNER_UPDATE ) + debug_logf(rna_trace, nullptr, "RNA Banner log: true\n"); } if ( rle.user ) @@ -172,7 +174,7 @@ bool RnaLogger::log(uint16_t type, uint16_t subtype, const struct in6_addr* src_ assert(ht); RnaLoggerEvent rle(type, subtype, src_mac, ht, hm, proto, cond_var, - ha, fp, hc, user, appid, di, jb); + ha, fp, hc, user, appid, di, jb, p); if ( src_ip and (!IN6_IS_ADDR_V4MAPPED(src_ip) or src_ip->s6_addr32[3]) ) rle.ip = src_ip; else diff --git a/src/network_inspectors/rna/rna_logger.h b/src/network_inspectors/rna/rna_logger.h index 76d2eed93..5521ce47b 100644 --- a/src/network_inspectors/rna/rna_logger.h +++ b/src/network_inspectors/rna/rna_logger.h @@ -38,9 +38,9 @@ struct RnaLoggerEvent : public Event RnaLoggerEvent (uint16_t t, uint16_t st, const uint8_t* mc, const RnaTracker* rt, const snort::HostMac* hmp, uint16_t pr, void* cv, const snort::HostApplication* hap, const snort::FpFingerprint* fpr, const snort::HostClient* hcp, const char* u, - int32_t app, const char* di, bool jb) : type(t), subtype(st), mac(mc), ht(rt), hm(hmp), - proto(pr), cond_var(cv), ha(hap), fp(fpr), hc(hcp), user(u), appid(app), - device_info(di), jail_broken(jb) { } + int32_t app, const char* di, bool jb, const snort::Packet* p) : type(t), subtype(st), + mac(mc), ht(rt), hm(hmp), proto(pr), cond_var(cv), ha(hap), fp(fpr), hc(hcp), + user(u), appid(app), device_info(di), jail_broken(jb), pkt(p) { } uint32_t event_time = 0; uint16_t type; @@ -58,6 +58,7 @@ struct RnaLoggerEvent : public Event AppId appid; const char* device_info; bool jail_broken; + const snort::Packet* pkt; }; class RnaLogger diff --git a/src/network_inspectors/rna/rna_logger_common.h b/src/network_inspectors/rna/rna_logger_common.h index 87e45248b..38bdfbfd5 100644 --- a/src/network_inspectors/rna/rna_logger_common.h +++ b/src/network_inspectors/rna/rna_logger_common.h @@ -39,6 +39,7 @@ #define CHANGE_HOST_UPDATE 15 #define CHANGE_HOST_TYPE 16 #define CHANGE_VLAN_TAG 18 + #define CHANGE_BANNER_UPDATE 24 #define CHANGE_CLIENT_APP_UPDATE 32 #define RUA_EVENT 1004