dns: improved handling of corrupt additionals

Ticket: 7228

That means log the rest of queries and answers, even if the
final field additionals is corrupt.
Set an event in this case.
pull/12371/head
Philippe Antoine 2 years ago committed by Victor Julien
parent 494d7bfe99
commit 6291e220e4

@ -17,3 +17,6 @@ alert dns any any -> any any (msg:"SURICATA DNS Infinite loop"; app-layer-event:
# Suricata's maximum number of DNS name labels was reached while parsing a resource name. # Suricata's maximum number of DNS name labels was reached while parsing a resource name.
alert dns any any -> any any (msg:"SURICATA DNS Too many labels"; app-layer-event:dns.too_many_labels; classtype:protocol-command-decode; sid:224010; rev:1;) alert dns any any -> any any (msg:"SURICATA DNS Too many labels"; app-layer-event:dns.too_many_labels; classtype:protocol-command-decode; sid:224010; rev:1;)
alert dns any any -> any any (msg:"SURICATA DNS invalid additionals"; app-layer-event:dns.invalid_additionals; classtype:protocol-command-decode; sid:2240011; rev:1;)
alert dns any any -> any any (msg:"SURICATA DNS invalid authorities"; app-layer-event:dns.invalid_authorities; classtype:protocol-command-decode; sid:2240012; rev:1;)

@ -135,6 +135,8 @@ pub enum DNSEvent {
InfiniteLoop, InfiniteLoop,
/// Too many labels were found. /// Too many labels were found.
TooManyLabels, TooManyLabels,
InvalidAdditionals,
InvalidAuthorities,
} }
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
@ -256,7 +258,9 @@ pub struct DNSMessage {
pub queries: Vec<DNSQueryEntry>, pub queries: Vec<DNSQueryEntry>,
pub answers: Vec<DNSAnswerEntry>, pub answers: Vec<DNSAnswerEntry>,
pub authorities: Vec<DNSAnswerEntry>, pub authorities: Vec<DNSAnswerEntry>,
pub invalid_authorities: bool,
pub additionals: Vec<DNSAnswerEntry>, pub additionals: Vec<DNSAnswerEntry>,
pub invalid_additionals: bool,
} }
#[derive(Debug, Default)] #[derive(Debug, Default)]
@ -399,6 +403,12 @@ pub(crate) fn dns_parse_request(input: &[u8]) -> Result<DNSTransaction, DNSParse
let opcode = ((request.header.flags >> 11) & 0xf) as u8; let opcode = ((request.header.flags >> 11) & 0xf) as u8;
let mut tx = DNSTransaction::new(Direction::ToServer); let mut tx = DNSTransaction::new(Direction::ToServer);
if request.invalid_additionals {
tx.set_event(DNSEvent::InvalidAdditionals);
}
if request.invalid_authorities {
tx.set_event(DNSEvent::InvalidAuthorities);
}
tx.request = Some(request); tx.request = Some(request);
if z_flag { if z_flag {
@ -452,6 +462,12 @@ pub(crate) fn dns_parse_response(input: &[u8]) -> Result<DNSTransaction, DNSPars
let flags = response.header.flags; let flags = response.header.flags;
let mut tx = DNSTransaction::new(Direction::ToClient); let mut tx = DNSTransaction::new(Direction::ToClient);
if response.invalid_additionals {
tx.set_event(DNSEvent::InvalidAdditionals);
}
if response.invalid_authorities {
tx.set_event(DNSEvent::InvalidAuthorities);
}
tx.response = Some(response); tx.response = Some(response);
if flags & 0x8000 == 0 { if flags & 0x8000 == 0 {
@ -1601,7 +1617,7 @@ mod tests {
fn test_dns_event_from_id() { fn test_dns_event_from_id() {
assert_eq!(DNSEvent::from_id(0), Some(DNSEvent::MalformedData)); assert_eq!(DNSEvent::from_id(0), Some(DNSEvent::MalformedData));
assert_eq!(DNSEvent::from_id(3), Some(DNSEvent::ZFlagSet)); assert_eq!(DNSEvent::from_id(3), Some(DNSEvent::ZFlagSet));
assert_eq!(DNSEvent::from_id(9), None); assert_eq!(DNSEvent::from_id(99), None);
} }
#[test] #[test]

@ -461,17 +461,40 @@ pub fn dns_parse_body<'a>(
header.questions as usize, header.questions as usize,
)(i)?; )(i)?;
let (i, answers) = dns_parse_answer(i, message, header.answer_rr as usize, &mut flags)?; let (i, answers) = dns_parse_answer(i, message, header.answer_rr as usize, &mut flags)?;
let (i, authorities) = dns_parse_answer(i, message, header.authority_rr as usize, &mut flags)?;
let (i, additionals) = dns_parse_answer(i, message, header.additional_rr as usize, &mut flags)?; let mut invalid_authorities = false;
let mut authorities = Vec::new();
let mut i_next = i;
let authorities_parsed = dns_parse_answer(i, message, header.authority_rr as usize, &mut flags);
if let Ok((i, authorities_ok)) = authorities_parsed {
authorities = authorities_ok;
i_next = i;
} else {
invalid_authorities = true;
}
let mut invalid_additionals = false;
let mut additionals = Vec::new();
if !invalid_authorities {
let additionals_parsed = dns_parse_answer(i_next, message, header.additional_rr as usize, &mut flags);
if let Ok((i, additionals_ok)) = additionals_parsed {
additionals = additionals_ok;
i_next = i;
} else {
invalid_additionals = true;
}
}
Ok(( Ok((
i, i_next,
( (
DNSMessage { DNSMessage {
header, header,
queries, queries,
answers, answers,
authorities, authorities,
invalid_authorities,
additionals, additionals,
invalid_additionals,
}, },
flags, flags,
), ),

Loading…
Cancel
Save