Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dns: improved handling of corrupt additionals #12349

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions rules/dns-events.rules
Original file line number Diff line number Diff line change
Expand Up @@ -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.
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;)
18 changes: 17 additions & 1 deletion rust/src/dns/dns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@ pub enum DNSEvent {
InfiniteLoop,
/// Too many labels were found.
TooManyLabels,
InvalidAdditionals,
InvalidAuthorities,
}

#[derive(Debug, PartialEq, Eq)]
Expand Down Expand Up @@ -256,7 +258,9 @@ pub struct DNSMessage {
pub queries: Vec<DNSQueryEntry>,
pub answers: Vec<DNSAnswerEntry>,
pub authorities: Vec<DNSAnswerEntry>,
pub invalid_authorities: bool,
pub additionals: Vec<DNSAnswerEntry>,
pub invalid_additionals: bool,
}

#[derive(Debug, Default)]
Expand Down Expand Up @@ -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 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);

if z_flag {
Expand Down Expand Up @@ -452,6 +462,12 @@ pub(crate) fn dns_parse_response(input: &[u8]) -> Result<DNSTransaction, DNSPars
let flags = response.header.flags;

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

if flags & 0x8000 == 0 {
Expand Down Expand Up @@ -1601,7 +1617,7 @@ mod tests {
fn test_dns_event_from_id() {
assert_eq!(DNSEvent::from_id(0), Some(DNSEvent::MalformedData));
assert_eq!(DNSEvent::from_id(3), Some(DNSEvent::ZFlagSet));
assert_eq!(DNSEvent::from_id(9), None);
assert_eq!(DNSEvent::from_id(99), None);
}

#[test]
Expand Down
29 changes: 26 additions & 3 deletions rust/src/dns/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -461,17 +461,40 @@ pub fn dns_parse_body<'a>(
header.questions as usize,
)(i)?;
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((
i,
i_next,
(
DNSMessage {
header,
queries,
answers,
authorities,
invalid_authorities,
additionals,
invalid_additionals,
},
flags,
),
Expand Down
Loading