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::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);

@ -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.");

@ -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:

Loading…
Cancel
Save