diff --git a/lib/src/analysis/analyzer.rs b/lib/src/analysis/analyzer.rs index b06a60a..2a842a5 100644 --- a/lib/src/analysis/analyzer.rs +++ b/lib/src/analysis/analyzer.rs @@ -11,6 +11,7 @@ use super::{ connection_redirect_downgrade::ConnectionRedirect2GDowngradeAnalyzer, imsi_requested::ImsiRequestedAnalyzer, information_element::InformationElement, null_cipher::NullCipherAnalyzer, priority_2g_downgrade::LteSib6And7DowngradeAnalyzer, + nas_null_cipher::NasNullCipherAnalyzer, }; #[derive(Debug, Clone, Deserialize, Serialize)] @@ -20,6 +21,7 @@ pub struct AnalyzerConfig { pub connection_redirect_2g_downgrade: bool, pub lte_sib6_and_7_downgrade: bool, pub null_cipher: bool, + pub nas_null_cipher: bool, } impl Default for AnalyzerConfig { @@ -29,6 +31,7 @@ impl Default for AnalyzerConfig { connection_redirect_2g_downgrade: true, lte_sib6_and_7_downgrade: true, null_cipher: true, + nas_null_cipher: true } } } @@ -162,6 +165,10 @@ impl Harness { harness.add_analyzer(Box::new(NullCipherAnalyzer {})); } + if analyzer_config.nas_null_cipher { + harness.add_analyzer(Box::new(NasNullCipherAnalyzer::new())) + } + harness } diff --git a/lib/src/analysis/mod.rs b/lib/src/analysis/mod.rs index cb733e2..46c5ea1 100644 --- a/lib/src/analysis/mod.rs +++ b/lib/src/analysis/mod.rs @@ -4,5 +4,6 @@ pub mod imsi_provided; pub mod imsi_requested; pub mod information_element; pub mod null_cipher; +pub mod nas_null_cipher; pub mod priority_2g_downgrade; pub mod util; diff --git a/lib/src/analysis/nas_null_cipher.rs b/lib/src/analysis/nas_null_cipher.rs new file mode 100644 index 0000000..08343c8 --- /dev/null +++ b/lib/src/analysis/nas_null_cipher.rs @@ -0,0 +1,60 @@ +use std::borrow::Cow; + +use pycrate_rs::nas::emm::EMMMessage; +use pycrate_rs::nas::generated::emm::emm_security_mode_command::NASSecAlgoCiphAlgo::EPSEncryptionAlgorithmEEA0Null; +use pycrate_rs::nas::NASMessage; + +use super::analyzer::{Analyzer, Event, EventType, Severity}; +use super::information_element::{InformationElement, LteInformationElement}; + +pub struct NasNullCipherAnalyzer { + packet_num: usize, +} + +impl Default for NasNullCipherAnalyzer { + fn default() -> Self { + Self::new() + } +} + +impl NasNullCipherAnalyzer { + pub fn new() -> Self { + Self { packet_num: 0 } + } +} + +impl Analyzer for NasNullCipherAnalyzer { + fn get_name(&self) -> Cow { + Cow::from("NAS Null Cipher Requested") + } + + fn get_description(&self) -> Cow { + Cow::from("Tests whether the MME requests to use a null cipher in the security mode command") + } + + fn analyze_information_element(&mut self, ie: &InformationElement) -> Option { + self.packet_num += 1; + let payload = match ie { + InformationElement::LTE(inner) => match &**inner { + LteInformationElement::NAS(payload) => payload, + _ => return None, + }, + _ => return None, + }; + + if let NASMessage::EMMMessage(EMMMessage::EMMSecurityModeCommand(req)) = payload { + if req.nas_sec_algo.inner.ciph_algo == EPSEncryptionAlgorithmEEA0Null { + return Some(Event { + event_type: EventType::QualitativeWarning { + severity: Severity::High, + }, + message: format!( + "NAS Security mode command requested null cipher(packet {})", + self.packet_num + ), + }); + } + } + None + } +}