#include "appid_session_api.h"
#include "app_info_table.h"
#include "service_plugins/service_ssl.h"
+#include "pub_sub/shadowtraffic_aggregator.h"
#include "tp_appid_session_api.h"
using namespace snort;
OdpContext& odp_ctxt = ctxt.get_odp_ctxt();
odp_ctxt.set_appid_shadow_traffic_status(status);
}
+
+void AppIdApi::set_ssl_certificate_key(const Flow& flow, const std::string& cert_key)
+{
+ AppIdSession* asd = get_appid_session(flow);
+ if (asd != nullptr and !cert_key.empty())
+ asd->set_cert_key(cert_key);
+}
+
+void AppIdApi::ssl_hostname_cert_lookup_verdict(const snort::Flow &flow, DomainFrontingStatus status)
+{
+ AppIdSession* asd = get_appid_session(flow);
+ if (asd != nullptr and status == DomainFrontingStatus::MISMATCH)
+ {
+ uint32_t shadow_bits = asd->get_shadow_traffic_bits();
+ shadow_bits |= ShadowTraffic_Type_Domain_Fronting;
+ asd->set_shadow_traffic_bits(shadow_bits);
+ AppId payload_id = asd->get_api().get_payload_app_id();
+ asd->set_shadow_traffic_publishing_appid(payload_id);
+ }
+}
#include "sfip/sf_ip.h"
#include "appid_session_api.h"
#include "application_ids.h"
+#include "pub_sub/domain_fronting.h"
enum class IpProtocol : uint8_t;
const char* get_appid_detector_directory() const;
void reset_appid_cpu_profiler_stats();
void update_shadow_traffic_status(bool status);
+ void set_ssl_certificate_key(const Flow& flow, const std::string& cert_key);
+ void ssl_hostname_cert_lookup_verdict(const snort::Flow &flow, DomainFrontingStatus status);
bool is_service_http_type(AppId service_id) const
{
#include "detector_plugins/detector_dns.h"
#include "detector_plugins/http_url_patterns.h"
#include "host_port_app_cache.h"
+#include "pub_sub/domain_fronting.h"
#include "service_plugins/service_discovery.h"
#include "tp_lib_handler.h"
#include "tp_appid_utils.h"
}
if ((pkt_thread_odp_ctxt->get_version() == api.asd->get_odp_ctxt_version()) and api.asd->get_odp_ctxt().get_appid_shadow_traffic_status())
- {
+ {
+ check_domain_fronting_status();
+
if (get_shadow_traffic_publishing_appid() > APP_ID_NONE)
{
if (api.asd->appid_shadow_traffic_bits != 0)
set_shadow_traffic_publishing_appid(publishing_appid);
}
}
+
+void AppIdSession::check_domain_fronting_status()
+{
+ if (api.asd->get_session_flags(APPID_SESSION_DECRYPTED) or api.asd->get_session_flags(APPID_SESSION_APP_REINSPECT))
+ {
+ AppIdHttpSession* hsession = api.asd->get_http_session();
+ Packet* p = DetectionEngine::get_current_packet();
+ if (hsession)
+ {
+ const char* host = hsession->get_cfield(REQ_HOST_FID);
+ if (host)
+ TLSDomainFrontCheckEvent(p, api.asd->get_cert_key(), host);
+ }
+ }
+}
void publish_shadow_traffic_event(const uint32_t& shadow_traffic_bits,snort::Flow*)const;
void process_shadow_traffic_appids();
void check_shadow_traffic_bits(AppId id, uint32_t& shadow_bits, AppId &publishing_appid, bool& is_publishing_set);
+ void check_domain_fronting_status();
bool need_to_delete_tp_conn(ThirdPartyAppIdContext*) const;
str.append(tempStr);
}
+
+ void set_cert_key (const std::string& key)
+ {
+ ssl_cert_key = key;
+ }
+
+ const std::string& get_cert_key() const
+ {
+ return ssl_cert_key;
+ }
private:
uint16_t prev_httpx_raw_packet = 0;
bool no_service_candidate = false;
bool no_service_inspector = false;
bool client_info_unpublished = false;
+ string ssl_cert_key;
uint32_t appid_shadow_traffic_bits = 0;
AppId shadow_traffic_appid = APP_ID_NONE;
};
static SnortProtocolId dummy_http2_protocol_id = 1;
char const* APPID_UT_ORG_UNIT = "Google";
THREAD_LOCAL bool TimeProfilerStats::enabled = false;
+#define ShadowTraffic_Type_Domain_Fronting 0x00000010
namespace snort
{
CHECK_EQUAL(id, 1492);
}
+TEST(appid_api, set_ssl_certificate_key)
+{
+ AppIdConfig config;
+ OdpContext odpctxt(config, nullptr);
+ SfIp ip{};
+ AppIdSession asd(IpProtocol::TCP, &ip, 1492, dummy_appid_inspector, odpctxt, 0
+#ifndef DISABLE_TENANT_ID
+ ,0
+#endif
+ );
+ string cert_key = "valid_certificate_key";
+ appid_api.set_ssl_certificate_key(*flow, cert_key);
+ asd.set_cert_key(cert_key);
+ CHECK_EQUAL(asd.get_cert_key(), cert_key);
+ delete &asd.get_api();
+}
+
+TEST(appid_api, ssl_hostname_cert_lookup_verdict)
+{
+ AppIdConfig config;
+ OdpContext odpctxt(config, nullptr);
+ SfIp ip{};
+ AppIdSession asd(IpProtocol::TCP, &ip, 1492, dummy_appid_inspector, odpctxt, 0
+#ifndef DISABLE_TENANT_ID
+ ,0
+#endif
+ );
+ AppidChangeBits change_bits;
+ asd.set_ss_application_ids(APPID_UT_ID, APPID_UT_ID, APPID_UT_ID,
+ APPID_UT_ID, APPID_UT_ID, change_bits);
+ DomainFrontingStatus status = DomainFrontingStatus::MISMATCH;
+ appid_api.ssl_hostname_cert_lookup_verdict(*flow, status);
+
+ AppId id = asd.get_api().get_payload_app_id();
+ asd.set_shadow_traffic_publishing_appid(id);
+ CHECK_EQUAL(asd.get_shadow_traffic_publishing_appid(), APPID_UT_ID);
+
+ uint32_t expected_shadow_bits = ShadowTraffic_Type_Domain_Fronting;
+ asd.set_shadow_traffic_bits(expected_shadow_bits);
+ CHECK_EQUAL(asd.get_shadow_traffic_bits(), expected_shadow_bits);
+ delete &asd.get_api();
+}
+
TEST(appid_api, ssl_app_group_id_lookup)
{
mock().expectNCalls(7, "publish");
daq_message_event.h
dcerpc_events.h
dhcp_events.h
+ domain_fronting.h
eve_process_event.h
expect_events.h
external_event_ids.h
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2022-2025 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+// domain_fronting.h author Bhumika Sachdeva <bsachdev@cisco.com>
+
+#ifndef DOMAIN_FRONTING_H
+#define DOMAIN_FRONTING_H
+
+#include "framework/data_bus.h"
+#include <string>
+
+enum class DomainFrontingStatus
+{
+ MISMATCH,
+ MATCHES,
+ CERT_NOT_IN_CACHE
+};
+
+class TLSDomainFrontCheckEvent : public snort::DataEvent
+{
+public:
+ TLSDomainFrontCheckEvent(const snort::Packet& packet, const std::string& certificate_id,
+ const std::string& hostname): cert_id(certificate_id), hostname(hostname), pkt(&packet) {}
+
+ const snort::Packet* get_packet() const override
+ { return pkt; }
+
+private:
+ const std::string cert_id;
+ const std::string hostname;
+ const snort::Packet* pkt;
+};
+
+#endif