From: Lukas Sismis Date: Thu, 19 Sep 2024 07:24:01 +0000 (+0200) Subject: ssh: add option to select behavior of encrypted parts X-Git-Tag: suricata-8.0.0-beta1~50 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5e8c775d77badd1afc92f7290716739955d56cdb;p=thirdparty%2Fsuricata.git ssh: add option to select behavior of encrypted parts Ticket: 6788 --- diff --git a/rust/src/ssh/ssh.rs b/rust/src/ssh/ssh.rs index 4c8b19be56..649bea74db 100644 --- a/rust/src/ssh/ssh.rs +++ b/rust/src/ssh/ssh.rs @@ -26,13 +26,28 @@ use suricata_sys::sys::AppProto; use std::ffi::CString; use std::sync::atomic::{AtomicBool, Ordering}; +#[repr(C)] +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[allow(non_camel_case_types)] +pub enum SshEncryptionHandling { + SSH_HANDLE_ENCRYPTION_TRACK_ONLY = 0, // Disable raw content inspection, continue tracking + SSH_HANDLE_ENCRYPTION_BYPASS = 1, // Skip processing of flow, bypass if possible + SSH_HANDLE_ENCRYPTION_FULL = 2, // Handle fully like any other protocol +} + static mut ALPROTO_SSH: AppProto = ALPROTO_UNKNOWN; static HASSH_ENABLED: AtomicBool = AtomicBool::new(false); +static mut ENCRYPTION_BYPASS_ENABLED: SshEncryptionHandling = SshEncryptionHandling::SSH_HANDLE_ENCRYPTION_TRACK_ONLY; + fn hassh_is_enabled() -> bool { HASSH_ENABLED.load(Ordering::Relaxed) } +fn encryption_bypass_mode() -> SshEncryptionHandling { + unsafe { ENCRYPTION_BYPASS_ENABLED } +} + #[derive(AppLayerFrameType)] pub enum SshFrameType { RecordHdr, @@ -203,13 +218,24 @@ impl SSHState { parser::MessageCode::NewKeys => { hdr.flags = SSHConnectionState::SshStateFinished; if ohdr.flags >= SSHConnectionState::SshStateFinished { - unsafe { - AppLayerParserStateSetFlag( - pstate, - APP_LAYER_PARSER_NO_INSPECTION + let mut flags = 0; + + match encryption_bypass_mode() { + SshEncryptionHandling::SSH_HANDLE_ENCRYPTION_BYPASS => { + flags |= APP_LAYER_PARSER_NO_INSPECTION | APP_LAYER_PARSER_NO_REASSEMBLY - | APP_LAYER_PARSER_BYPASS_READY, - ); + | APP_LAYER_PARSER_BYPASS_READY; + } + SshEncryptionHandling::SSH_HANDLE_ENCRYPTION_TRACK_ONLY => { + flags |= APP_LAYER_PARSER_NO_INSPECTION; + } + _ => {} + } + + if flags != 0 { + unsafe { + AppLayerParserStateSetFlag(pstate, flags); + } } } } @@ -553,6 +579,13 @@ pub extern "C" fn SCSshHasshIsEnabled() -> bool { hassh_is_enabled() } +#[no_mangle] +pub extern "C" fn SCSshEnableBypass(mode: SshEncryptionHandling) { + unsafe { + ENCRYPTION_BYPASS_ENABLED = mode; + } +} + #[no_mangle] pub unsafe extern "C" fn SCSshTxGetLogCondition(tx: *mut std::os::raw::c_void) -> bool { let tx = cast_pointer!(tx, SSHTransaction); diff --git a/src/app-layer-ssh.c b/src/app-layer-ssh.c index e82183c0a3..9223a418b3 100644 --- a/src/app-layer-ssh.c +++ b/src/app-layer-ssh.c @@ -55,6 +55,8 @@ /* HASSH fingerprints are disabled by default */ #define SSH_CONFIG_DEFAULT_HASSH false +/* Bypassing the encrypted part of the connections */ +#define SSH_CONFIG_DEFAULT_ENCRYPTION_BYPASS SSH_HANDLE_ENCRYPTION_TRACK_ONLY static int SSHRegisterPatternsForProtocolDetection(void) { @@ -103,6 +105,25 @@ void RegisterSSHParsers(void) if (RunmodeIsUnittests() || enable_hassh) { SCSshEnableHassh(); } + + SshEncryptionHandling encryption_bypass = SSH_CONFIG_DEFAULT_ENCRYPTION_BYPASS; + SCConfNode *encryption_node = SCConfGetNode("app-layer.protocols.ssh.encryption-handling"); + if (encryption_node != NULL && encryption_node->val != NULL) { + if (strcmp(encryption_node->val, "full") == 0) { + encryption_bypass = SSH_HANDLE_ENCRYPTION_FULL; + } else if (strcmp(encryption_node->val, "track-only") == 0) { + encryption_bypass = SSH_HANDLE_ENCRYPTION_TRACK_ONLY; + } else if (strcmp(encryption_node->val, "bypass") == 0) { + encryption_bypass = SSH_HANDLE_ENCRYPTION_BYPASS; + } else { + encryption_bypass = SSH_CONFIG_DEFAULT_ENCRYPTION_BYPASS; + } + } + + if (encryption_bypass) { + SCLogConfig("ssh: bypass on the start of encryption enabled"); + SCSshEnableBypass(encryption_bypass); + } } SCLogDebug("Registering Rust SSH parser."); diff --git a/suricata.yaml.in b/suricata.yaml.in index 8623c80bf3..4365ce264b 100644 --- a/suricata.yaml.in +++ b/suricata.yaml.in @@ -968,6 +968,15 @@ app-layer: ssh: enabled: yes #hassh: yes + + # What to do when the encrypted communications start: + # - track-only: keep tracking but stop inspection (default) + # - full: keep tracking and inspect as normal + # - bypass: stop processing this flow as much as possible. + # Offload flow bypass to kernel or hardware if possible. + # For the best performance, select 'bypass'. + # + # encryption-handling: track-only doh2: enabled: yes http2: