Am I affected?

type your bandit version to check

Description

Inconsistent Interpretation of HTTP Requests ('HTTP Request/Response Smuggling') vulnerability in the HTTP/1.1 chunked body reader of mtrudel bandit allows an unauthenticated remote attacker to smuggle a second request past a front-end proxy via a chunk extension that contains a bare LF.

The chunked reader in lib/bandit/http1/socket.ex takes the chunk-size line to be everything up to the first CRLF and discards everything after ; without checking it against the RFC 9112 chunk-ext grammar, so bare LF, bare CR and other control bytes pass. A proxy that ends the size line at a bare LF reads 2;\nxx\r\n40\r\n... as one request whose second chunk holds a GET /admin, while Bandit ends the body early and dispatches GET /admin as a separate pipelined request. Deployments without such a proxy in front of Bandit are not affected.

This issue affects bandit: from 1.12.4 before 1.14.0.

Technical analysis

1. Unchecked extension. In lib/bandit/http1/socket.ex, the chunked body reader takes the chunk-size line to be everything up to the first CRLF. Anything after ; is thrown away without being checked against the RFC 9112 §7.1.1 chunk-ext grammar, so bare LF, bare CR and other control bytes are accepted. The 16-byte size-line cap does not help, because the payload needs only 5 bytes.

2. Bandit's reading. For the body 2;\nxx\r\n40\r\n0\r\n\r\nGET /admin ..., Bandit takes 2;\nxx as the size line and 40 as the 2-byte chunk, and the embedded 0\r\n\r\n ends the body. Bandit then runs GET /admin as a second pipelined request.

3. The proxy's reading. A proxy that ends the size line at the bare LF sees only one POST, with the chunk xx and a 0x40-byte chunk that holds the GET /admin bytes.

Proof of concept

  1. Run Bandit with a Plug that reads the body and records each request's method and path.
  2. On one connection, send POST /public with Transfer-Encoding: chunked and the body 2;\nxx\r\n40\r\n0\r\n\r\n, followed directly by GET /admin HTTP/1.1 with Content-Length: 7 and the body \r\n0\r\n\r\n.
  3. Bandit dispatches both POST /public with the body 40 and GET /admin. A proxy that ends lines at a bare LF would have forwarded the same bytes as the single POST /public.

Weaknesses & attack patterns

Weakness

CWE-444 · Inconsistent Interpretation of HTTP Requests ('HTTP Request/Response Smuggling') in catalog → MITRE ↗

Attack patterns

CAPEC-33 · HTTP Request Smuggling MITRE ↗

Behind a front-end proxy that treats a bare LF as a line ending and forwards chunked bodies unchanged, an unauthenticated attacker can have Bandit run requests the proxy never saw, getting past the proxy's access controls.

Affected — Hex / bandit Hex.pm ↗ Repository ↗

≥ 1.12.4 < 1.14.0 affected
every other version: unaffected
cpe cpe:2.3:a:mtrudel:bandit:*:*:*:*:*:*:*:*
version type semver

Affected — GitHub / mtrudel/bandit Repository ↗

≥ c31e9e3 < 220b9df affected
every other version: unaffected
cpe cpe:2.3:a:mtrudel:bandit:*:*:*:*:*:*:*:*
version type git

Workarounds

Where the front-end proxy can reach Bandit over HTTP/2, disable HTTP/1 with http_1_options: [enabled: false], so that the chunked body reader never runs.

References

Credits

Peter Ullrich Reporter
Mat Trudel Remediation developer
Jonatan Männchen / EEF Analyst

CVSS breakdown

CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:L/VA:N/SC:L/SI:L/SA:N
« All CVEs