ssh: add option to select behavior of encrypted parts

Ticket: 6788
pull/12965/head
Lukas Sismis 2 years ago committed by Victor Julien
parent 185123a130
commit 5e8c775d77

@ -26,13 +26,28 @@ use suricata_sys::sys::AppProto;
use std::ffi::CString; use std::ffi::CString;
use std::sync::atomic::{AtomicBool, Ordering}; 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 mut ALPROTO_SSH: AppProto = ALPROTO_UNKNOWN;
static HASSH_ENABLED: AtomicBool = AtomicBool::new(false); static HASSH_ENABLED: AtomicBool = AtomicBool::new(false);
static mut ENCRYPTION_BYPASS_ENABLED: SshEncryptionHandling = SshEncryptionHandling::SSH_HANDLE_ENCRYPTION_TRACK_ONLY;
fn hassh_is_enabled() -> bool { fn hassh_is_enabled() -> bool {
HASSH_ENABLED.load(Ordering::Relaxed) HASSH_ENABLED.load(Ordering::Relaxed)
} }
fn encryption_bypass_mode() -> SshEncryptionHandling {
unsafe { ENCRYPTION_BYPASS_ENABLED }
}
#[derive(AppLayerFrameType)] #[derive(AppLayerFrameType)]
pub enum SshFrameType { pub enum SshFrameType {
RecordHdr, RecordHdr,
@ -203,13 +218,24 @@ impl SSHState {
parser::MessageCode::NewKeys => { parser::MessageCode::NewKeys => {
hdr.flags = SSHConnectionState::SshStateFinished; hdr.flags = SSHConnectionState::SshStateFinished;
if ohdr.flags >= SSHConnectionState::SshStateFinished { if ohdr.flags >= SSHConnectionState::SshStateFinished {
unsafe { let mut flags = 0;
AppLayerParserStateSetFlag(
pstate, match encryption_bypass_mode() {
APP_LAYER_PARSER_NO_INSPECTION SshEncryptionHandling::SSH_HANDLE_ENCRYPTION_BYPASS => {
flags |= APP_LAYER_PARSER_NO_INSPECTION
| APP_LAYER_PARSER_NO_REASSEMBLY | 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() hassh_is_enabled()
} }
#[no_mangle]
pub extern "C" fn SCSshEnableBypass(mode: SshEncryptionHandling) {
unsafe {
ENCRYPTION_BYPASS_ENABLED = mode;
}
}
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn SCSshTxGetLogCondition(tx: *mut std::os::raw::c_void) -> bool { pub unsafe extern "C" fn SCSshTxGetLogCondition(tx: *mut std::os::raw::c_void) -> bool {
let tx = cast_pointer!(tx, SSHTransaction); let tx = cast_pointer!(tx, SSHTransaction);

@ -55,6 +55,8 @@
/* HASSH fingerprints are disabled by default */ /* HASSH fingerprints are disabled by default */
#define SSH_CONFIG_DEFAULT_HASSH false #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) static int SSHRegisterPatternsForProtocolDetection(void)
{ {
@ -103,6 +105,25 @@ void RegisterSSHParsers(void)
if (RunmodeIsUnittests() || enable_hassh) { if (RunmodeIsUnittests() || enable_hassh) {
SCSshEnableHassh(); 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."); SCLogDebug("Registering Rust SSH parser.");

@ -968,6 +968,15 @@ app-layer:
ssh: ssh:
enabled: yes enabled: yes
#hassh: 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: doh2:
enabled: yes enabled: yes
http2: http2:

Loading…
Cancel
Save