CVE-2024-28871: Insufficient Information (NVD-CWE-noinfo)
value: LibHTP is a security-aware parser for the HTTP protocol and the related bits and pieces. Version 0.5.46 may parse malformed request traffic, leading to excessive CPU usage. Version 0.5.47 contains a patch for the issue. No known workarounds are available.
CWE description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
Published: 2024-04-04T15:15Z
Repository: https://github.com/OISF/libhtp
Language: C
Files changed: htp/htp_request.c
Commit date: 2024-03-07 16:23:28 +0100
Commit message: request: limit probing after missing protocol

And do not consider HTTP/0.9 if there is too much junk afterward.

Avoids quadratic complexity with probing many whitespaces lines.

Ticket: 6757

Fixes: bf618ec7f243 ("http0.9: process headers if there are non-space characters")

Diff: diff --git a/htp/htp_request.c b/htp/htp_request.c
index 2138831d..9fddbd8f 100644
--- a/htp/htp_request.c
+++ b/htp/htp_request.c
@@ -730,10 +730,18 @@ htp_status_t htp_connp_REQ_HEADERS(htp_connp_t *connp) {
     }
 
     return HTP_ERROR;
 }
 
+// HTTP/0.9 is supposed to be only a request line without protocol.
+// Libhtp will still consider the request to be HTTP/0.9 if there
+// are some junk whitespaces after that request line.
+// Libhtp allows the small value of 16 extra bytes/whitespaces,
+// otherwise we consider it to be a HTTP/1.x request with missing protocol.
+// It is unlikely to meet HTTP/0.9, and we want to limit probing.
+#define HTTP09_MAX_JUNK_LEN 16
+
 /**
  * Determines request protocol.
  *
  * @param[in] connp
  * @returns HTP_OK on state change, HTP_ERROR on error, or HTP_DATA when more data is needed.
@@ -747,10 +755,18 @@ htp_status_t htp_connp_REQ_PROTOCOL(htp_connp_t *connp) {
         connp->in_tx->request_progress = HTP_REQUEST_HEADERS;
     } else {
         // Let's check if the protocol was simply missing
         int64_t pos = connp->in_current_read_offset;
         // Probe if data looks like a header line
+        if (connp->in_current_len > connp->in_current_read_offset + HTTP09_MAX_JUNK_LEN) {
+            htp_log(connp, HTP_LOG_MARK, HTP_LOG_WARNING, 0, "Request line: missing protocol");
+            connp->in_tx->is_protocol_0_9 = 0;
+            // Switch to request header parsing.
+            connp->in_state = htp_connp_REQ_HEADERS;
+            connp->in_tx->request_progress = HTP_REQUEST_HEADERS;
+            return HTP_OK;
+        }
         while (pos < connp->in_current_len) {
             if (!htp_is_space(connp->in_current_data[pos])) {
                 htp_log(connp, HTP_LOG_MARK, HTP_LOG_WARNING, 0, "Request line: missing protocol");
                 connp->in_tx->is_protocol_0_9 = 0;
                 // Switch to request header parsing.

Fixed code: // HTTP/0.9 is supposed to be only a request line without protocol.
// Libhtp will still consider the request to be HTTP/0.9 if there
// are some junk whitespaces after that request line.
// Libhtp allows the small value of 16 extra bytes/whitespaces,
// otherwise we consider it to be a HTTP/1.x request with missing protocol.
// It is unlikely to meet HTTP/0.9, and we want to limit probing.
#define HTTP09_MAX_JUNK_LEN 16

        if (connp->in_current_len > connp->in_current_read_offset + HTTP09_MAX_JUNK_LEN) {
            htp_log(connp, HTP_LOG_MARK, HTP_LOG_WARNING, 0, "Request line: missing protocol");
            connp->in_tx->is_protocol_0_9 = 0;
            // Switch to request header parsing.
            connp->in_state = htp_connp_REQ_HEADERS;
            connp->in_tx->request_progress = HTP_REQUEST_HEADERS;
            return HTP_OK;
        }