CVE-2024-23835 (published 2024-02-26T16:27Z)

Suricata is a network Intrusion Detection System, Intrusion Prevention System and Network Security Monitoring engine.  Prior to version 7.0.3, excessive memory use during pgsql parsing could lead to OOM-related crashes.  This vulnerability is patched in 7.0.3.  As workaround, users can disable the pgsql app layer parser.


Weakness information:
cwe_id: NVD-CWE-noinfo
cwe_name: Insufficient Information
description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
extended_description: Insufficient Information

Fix information:
repo_url: https://github.com/OISF/suricata
commit_details: repo_url: https://github.com/OISF/suricata
author: Philippe Antoine
author_date: 2023-10-17 22:04:57+02:00
msg: pgsql: parse only PDU when type is unknown

A next PDU may already be in the slice to parse.
Do not skip its parsing, ie do not use rest, but take just
the length of the pdu
repository: repo_url: https://github.com/OISF/suricata
repo_name: OISF/suricata
description: Suricata is a network Intrusion Detection System, Intrusion Prevention System and Network Security Monitoring engine developed by the OISF and the Suricata community.
repo_language: C
owner: OISF
file_changes: filename: parser.rs
change_type: ModificationType.MODIFY
diff: @@ -23,7 +23,7 @@ use crate::common::nom7::take_until_and_consume;
 use nom7::branch::alt;
 use nom7::bytes::streaming::{tag, take, take_until, take_until1};
 use nom7::character::streaming::{alphanumeric1, char};
-use nom7::combinator::{all_consuming, cond, eof, map_parser, opt, peek, rest, verify};
+use nom7::combinator::{all_consuming, cond, eof, map_parser, opt, peek, verify};
 use nom7::error::{make_error, ErrorKind};
 use nom7::multi::{many1, many_m_n, many_till};
 use nom7::number::streaming::{be_i16, be_i32};
@@ -1078,10 +1078,12 @@ pub fn pgsql_parse_response(i: &[u8]) -> IResult<&[u8], PgsqlBEMessage> {
                 b'A' => parse_notification_response(i)?,
                 b'D' => parse_consolidated_data_row(i)?,
                 _ => {
-                    let (i, payload) = rest(i)?;
+                    let (i, identifier) = be_u8(i)?;
+                    let (i, length) = verify(be_u32, |&x| x > PGSQL_LENGTH_FIELD)(i)?;
+                    let (i, payload) = take(length - PGSQL_LENGTH_FIELD)(i)?;
                     let unknown = PgsqlBEMessage::UnknownMessageType (RegularPacket{
-                        identifier: pseudo_header.0,
-                        length: pseudo_header.1,
+                        identifier,
+                        length,
                         payload: payload.to_vec(),
                     });
                     (i, unknown)
@@ -1918,7 +1920,7 @@ mod tests {
         let res = PgsqlBEMessage::UnknownMessageType(RegularPacket {
             identifier: b'`',
             length: 54,
-            payload: bad_buf.to_vec(),
+            payload: bad_buf[5..].to_vec(),
         });
         assert_eq!(result, res);
         assert!(remainder.is_empty());

programming_language: Rust
repo_url: https://github.com/OISF/suricata
commit_details: repo_url: https://github.com/OISF/suricata
author: Philippe Antoine
author_date: 2023-10-17 22:01:27+02:00
msg: pgsql: parse auth message within its bound

If the next PDU is already in the slice next, do not use it and
restrict ourselves to the length of this PDU.
Avoids overconsumption of memory by quadratic complexity, when
having many small PDUS in one big chunk being parsed

Ticket: #6411
repository: repo_url: https://github.com/OISF/suricata
repo_name: OISF/suricata
description: Suricata is a network Intrusion Detection System, Intrusion Prevention System and Network Security Monitoring engine developed by the OISF and the Suricata community.
repo_language: C
owner: OISF
file_changes: filename: parser.rs
change_type: ModificationType.MODIFY
diff: @@ -719,7 +719,6 @@ fn pgsql_parse_authentication_message<'a>(i: &'a [u8]) -> IResult<&'a [u8], Pgsq
     let (i, identifier) = verify(be_u8, |&x| x == b'R')(i)?;
     let (i, length) = verify(be_u32, |&x| x >= 8)(i)?;
     let (i, auth_type) = be_u32(i)?;
-    let (i, payload) = peek(rest)(i)?;
     let (i, message) = map_parser(
         take(length - 8),
         |b: &'a [u8]| {
@@ -729,14 +728,14 @@ fn pgsql_parse_authentication_message<'a>(i: &'a [u8]) -> IResult<&'a [u8], Pgsq
                                 identifier,
                                 length,
                                 auth_type,
-                                payload: payload.to_vec(),
+                                payload: b.to_vec(),
                             }))),
                 3 => Ok((b, PgsqlBEMessage::AuthenticationCleartextPassword(
                             AuthenticationMessage {
                                 identifier,
                                 length,
                                 auth_type,
-                                payload: payload.to_vec(),
+                                payload: b.to_vec(),
                             }))),
                 5 => {
                     let (b, salt) = all_consuming(take(4_usize))(b)?;
@@ -753,7 +752,7 @@ fn pgsql_parse_authentication_message<'a>(i: &'a [u8]) -> IResult<&'a [u8], Pgsq
                                 identifier,
                                 length,
                                 auth_type,
-                                payload: payload.to_vec(),
+                                payload: b.to_vec(),
                             }))),
                 // TODO - For SASL, should we parse specific details of the challenge itself? (as seen in: https://github.com/launchbadge/sqlx/blob/master/sqlx-core/src/postgres/message/authentication.rs )
                 10 => {
@@ -767,23 +766,21 @@ fn pgsql_parse_authentication_message<'a>(i: &'a [u8]) -> IResult<&'a [u8], Pgsq
                                 })))
                 }
                 11 => {
-                    let (b, sasl_challenge) = rest(i)?;
                     Ok((b, PgsqlBEMessage::AuthenticationSASLContinue(
                                 AuthenticationMessage {
                                     identifier,
                                     length,
                                     auth_type,
-                                    payload: sasl_challenge.to_vec(),
+                                    payload: b.to_vec(),
                                 })))
                 },
                 12 => {
-                    let (i, signature) = take(length - 8)(i)?;
-                    Ok((i, PgsqlBEMessage::AuthenticationSASLFinal(
+                    Ok((b, PgsqlBEMessage::AuthenticationSASLFinal(
                                 AuthenticationMessage {
                                     identifier,
                                     length,
                                     auth_type,
-                                    payload: signature.to_vec(),
+                                    payload: b.to_vec(),
                                 }
                                 )))
                 }

programming_language: Rust