Project

General

Profile

Actions

Bug #8410

open

http2: response_frame_size is never set

Added by Philippe Antoine 6 days ago. Updated about 15 hours ago.

Status:
Resolved
Priority:
Normal
Target version:
Affected Versions:
Effort:
Difficulty:
Label:

Description

request_frame_size is set whatever the direction

Setting request_frame_size when we should set response_frame_size leads to FN

Submitted report:

[Summary]
`HTTP2State::parse_frames()` is called for both ToServer and ToClient directions, but unconditionally writes remaining frame bytes to `self.request_frame_size` (line 1153 of `rust/src/http2/http2.rs`). When a large (>=65536 bytes) server-to-client DATA frame is partially delivered, the remaining byte count is stored in `request_frame_size` instead of `response_frame_size`. On the next client-to-server data delivery, `parse_ts()` consumes `request_frame_size` bytes and discards them, causing all subsequent client HTTP/2 requests to be silently dropped from parsing and inspection.

[Root Cause]
`HTTP2State` maintains two fields for tracking remaining bytes of partially-delivered large frames:

```rust
// rust/src/http2/http2.rs:567-568
pub struct HTTP2State {
request_frame_size: u32, // used by parse_ts() at line 1343
response_frame_size: u32, // used by parse_tc() at line 1369
...
}
```

`parse_ts()` (ToServer) checks and consumes `self.request_frame_size` at lines 1343-1352. `parse_tc()` (ToClient) checks and consumes `self.response_frame_size` at lines 1369-1378. Both call the shared `parse_frames()` method.

Inside `parse_frames()`, when a frame with `length >= HTTP2_MAX_HANDLED_FRAME_SIZE` (65536) arrives partially (the available data contains at least `HTTP2_MIN_HANDLED_FRAME_SIZE` (256) bytes but not the full frame), line 1153 executes:

```rust
// rust/src/http2/http2.rs:1153
self.request_frame_size = head.length - (rem.len() as u32);
```

This always writes to `request_frame_size`, even when `parse_frames()` was called from `parse_tc()` with `dir Direction::ToClient`. The correct behavior would be:

```rust
if dir Direction::ToServer {
self.request_frame_size = head.length - (rem.len() as u32);
} else {
self.response_frame_size = head.length - (rem.len() as u32);
}
```

[PoC]
Please extract the attached compressed file and proceed.

1. docker build -t poc .
2. docker run --rm poc
스크린샷 2026-03-24 오후 9.51.45.png

[Impact]
- All client requests following a large server response are invisible to Suricata's detection engine. HTTP-based signature rules (`http.uri`, `http.method`, `http.request_header`, etc.) fail to match.
- This is trivially exploitable by any server an attacker controls. HTTP/2 responses >= 64KB are extremely common in normal web traffic.
- HTTP/2 is enabled by default in Suricata (`app-layer.protocols.http2.enabled: yes`).

[Affected Version]
  • Current `main` branch (commit bc4a055e7, Suricata 9.0.0-dev) is confirmed affected.

Files


Subtasks 1 (1 open0 closed)

Bug #8411: http2: response_frame_size is never set (8.0.x backport)In ReviewPhilippe AntoineActions
Actions #1

Updated by OISF Ticketbot 6 days ago

  • Subtask #8411 added
Actions #2

Updated by OISF Ticketbot 6 days ago

  • Label deleted (Needs backport to 8.0)
Actions #3

Updated by Philippe Antoine 6 days ago

  • Status changed from Assigned to In Progress
  • Label Needs backport to 7.0 added

Gitlab MR

I think this can be made public as a regular bug

This needs complicity between client and server to evade client detection, so not a security issue for me

Actions #4

Updated by OISF Ticketbot 6 days ago

  • Subtask #8412 added
Actions #5

Updated by OISF Ticketbot 6 days ago

  • Label deleted (Needs backport to 7.0)
Actions #6

Updated by Philippe Antoine 6 days ago

  • Status changed from In Progress to In Review
Actions #8

Updated by Victor Julien 5 days ago

  • Private changed from Yes to No

We will consider this to be a regular bug as to use this to evade Suricata it would need the attacker to control both the server and client to cooperate on this.

Actions #10

Updated by Philippe Antoine about 15 hours ago

  • Status changed from In Review to Resolved
Actions

Also available in: Atom PDF