diff --git a/doc/userguide/output/eve/eve-json-format.rst b/doc/userguide/output/eve/eve-json-format.rst index 88545f7deb..512cd6f6c7 100644 --- a/doc/userguide/output/eve/eve-json-format.rst +++ b/doc/userguide/output/eve/eve-json-format.rst @@ -1838,6 +1838,7 @@ Fields * "ikev1.server.nonce_payload_length", "ikev1.client.nonce_payload_length": Length of the nonce payload. * "ikev1.client.client_proposals": List of the security associations proposed to the server. * "ikev1.vendor_ids": List of the vendor IDs observed in the communication. +* "server_proposals": List of server proposals with parameters, if there are more than one. This is a non-standard case; this field is only present if such a situation was observed in the inspected traffic. diff --git a/doc/userguide/rules/ike-keywords.rst b/doc/userguide/rules/ike-keywords.rst index b8ee70277e..1d12ce329e 100644 --- a/doc/userguide/rules/ike-keywords.rst +++ b/doc/userguide/rules/ike-keywords.rst @@ -47,6 +47,8 @@ Match on an attribute value of the chosen Security Association (SA) by the Respo ``sa_field_size``. IKEv2 supports ``alg_enc``, ``alg_auth``, ``alg_prf`` and ``alg_dh``. +If there is more than one chosen SA the event ``MultipleServerProposal`` is set. The attributes of the first SA are used for this keyword. + Examples:: diff --git a/rules/ipsec-events.rules b/rules/ipsec-events.rules index 1ae6edffe6..ccfd65145c 100644 --- a/rules/ipsec-events.rules +++ b/rules/ipsec-events.rules @@ -17,3 +17,4 @@ alert ike any any -> any any (msg:"SURICATA IKE invalid proposal"; flow:to_serve alert ike any any -> any any (msg:"SURICATA IKE invalid proposal selected"; flow:to_client; app-layer-event:ike.invalid_proposal; classtype:protocol-command-decode; sid:2224010; rev:2;) alert ike any any -> any any (msg:"SURICATA IKE unknown proposal"; flow:to_server; app-layer-event:ike.unknown_proposal; classtype:protocol-command-decode; sid:2224011; rev:2;) alert ike any any -> any any (msg:"SURICATA IKE unknown proposal selected"; flow:to_client; app-layer-event:ike.unknown_proposal; classtype:protocol-command-decode; sid:2224012; rev:2;) +alert ike any any -> any any (msg:"SURICATA IKE multiple server proposal"; flow:to_client; app-layer-event:ike.multiple_server_proposal; classtype:protocol-command-decode; sid:2224013; rev:1;) diff --git a/rust/src/ike/detect.rs b/rust/src/ike/detect.rs index 787032bde4..78f60c8d67 100644 --- a/rust/src/ike/detect.rs +++ b/rust/src/ike/detect.rs @@ -151,17 +151,16 @@ pub extern "C" fn rs_ike_state_get_sa_attribute( if let Ok(sa) = sa_type_s { if tx.ike_version == 1 { - 'outer1: for (i, server_transform) in tx.hdr.ikev1_transforms.iter().enumerate() { - if i >= 1 { - debug_validate_bug_on!(true); - break; - } - for attr in server_transform { - if attr.attribute_type.to_string() == sa { - if let Some(numeric_value) = attr.numeric_value { - ret_val = numeric_value; - ret_code = 1; - break 'outer1; + if tx.hdr.ikev1_transforms.len() >= 1 { + // there should be only one chosen server_transform, check event + if let Some(server_transform) = tx.hdr.ikev1_transforms.first() { + for attr in server_transform { + if attr.attribute_type.to_string() == sa { + if let Some(numeric_value) = attr.numeric_value { + ret_val = numeric_value; + ret_code = 1; + break + } } } } diff --git a/rust/src/ike/ike.rs b/rust/src/ike/ike.rs index 8c87f1ab78..bcd6ffcec6 100644 --- a/rust/src/ike/ike.rs +++ b/rust/src/ike/ike.rs @@ -47,6 +47,7 @@ pub enum IkeEvent { InvalidProposal, UnknownProposal, PayloadExtraData, + MultipleServerProposal, } impl IkeEvent { @@ -63,6 +64,7 @@ impl IkeEvent { 8 => Some(IkeEvent::InvalidProposal), 9 => Some(IkeEvent::UnknownProposal), 10 => Some(IkeEvent::PayloadExtraData), + 11 => Some(IkeEvent::MultipleServerProposal), _ => None, } } @@ -456,6 +458,7 @@ pub extern "C" fn rs_ike_state_get_event_info_by_id( IkeEvent::InvalidProposal => "invalid_proposal\0", IkeEvent::UnknownProposal => "unknown_proposal\0", IkeEvent::PayloadExtraData => "payload_extra_data\0", + IkeEvent::MultipleServerProposal => "multiple_server_proposal\0", }; unsafe { *event_name = estr.as_ptr() as *const std::os::raw::c_char; @@ -490,6 +493,7 @@ pub extern "C" fn rs_ike_state_get_event_info( "invalid_proposal" => IkeEvent::InvalidProposal as i32, "unknown_proposal" => IkeEvent::UnknownProposal as i32, "payload_extra_data" => IkeEvent::PayloadExtraData as i32, + "multiple_server_proposal" => IkeEvent::MultipleServerProposal as i32, _ => -1, // unknown event } } diff --git a/rust/src/ike/ikev1.rs b/rust/src/ike/ikev1.rs index 043f2496f8..c7f85945e7 100644 --- a/rust/src/ike/ikev1.rs +++ b/rust/src/ike/ikev1.rs @@ -130,6 +130,15 @@ pub fn handle_ikev1( &tx.hdr.ikev1_transforms, ); } else { + if state.ikev1_container.server.transforms.len() <= 1 + && state.ikev1_container.server.transforms.len() + + tx.hdr.ikev1_transforms.len() + > 1 + { + SCLogDebug!("More than one chosen server proposal"); + state.set_event(IkeEvent::MultipleServerProposal); + } + state.ikev1_container.server.update( &to_hex(tx.hdr.ikev1_header.key_exchange.as_ref()), &to_hex(tx.hdr.ikev1_header.nonce.as_ref()), diff --git a/rust/src/ike/logger.rs b/rust/src/ike/logger.rs index 3a022a1f99..390231229e 100644 --- a/rust/src/ike/logger.rs +++ b/rust/src/ike/logger.rs @@ -73,14 +73,19 @@ fn log_ike( } if tx.ike_version == 1 { - let mut index = 0; - for server_transform in &state.ikev1_container.server.transforms { - if index >= 1 { - debug_validate_bug_on!(true); - break; + if state.ikev1_container.server.transforms.len() > 0 { + // log the first transform as the chosen one + add_attributes(&state.ikev1_container.server.transforms[0], jb)?; + } + if state.ikev1_container.server.transforms.len() > 1 { + // in case we have multiple server transforms log them in a list + jb.open_array("server_proposals")?; + for server_transform in &state.ikev1_container.server.transforms { + jb.start_object()?; + add_attributes(server_transform, jb)?; + jb.close()?; } - add_attributes(server_transform, jb)?; - index += 1; + jb.close()?; } } else if tx.ike_version == 2 { if tx.hdr.flags & IKEV2_FLAG_INITIATOR != 0 {