Gemeente Cyber Dreigingsradar
Kritiek
Terug naar het overzicht
KritiekLeveranciersincidentGitHub Security Advisories

Bandit: Unauthenticated one-shot DoS via `Transfer-Encoding: chunked`

Bandit: Unauthenticated one-shot DoS via `Transfer-Encoding: chunked`

Prioriteit & onderbouwing

49 / 100

Prioriteit: Laag

Monitoren

Laag (49/100): monitoren. Zwaarst wegend: technische ernst en betrouwbaarheid van het signaal.

Threat Score85 / 100

hoog

  • Technische ernst (severity): Genormaliseerde ernst 'critical'; geen CVSS-score beschikbaar.
Exploit Score10 / 100

laag

  • Geen exploit bekend: Er is geen exploit of actief misbruik bekend.
Municipal Relevance Score35 / 100

midden

  • Gemeentelijke relevantie: Relevantiescore 35/100 uit de relevantie-engine (module 5).
Action Urgency Score49 / 100

midden

  • Technische ernst: Threat Score 85/100 x gewicht 25%.
  • Exploitatie: Exploit Score 10/100 x gewicht 25%.
  • Gemeentelijke relevantie: Relevantiescore 35/100 x gewicht 22%.
  • Betrouwbaarheid van het signaal: Confidence 'likely' x gewicht 12%.
  • Blootstellingskans: Geschatte blootstelling 30% x gewicht 10%.
  • Betrouwbaarheid van de bron: Bronbetrouwbaarheid 88% x gewicht 6%.

De priority_score is de Action Urgency Score: een gewogen combinatie van de technische ernst, de exploitatie en de gemeentelijke relevantie.

Toelichting

### Summary Bandit's HTTP/1 chunked-body reader silently drops the request size cap that the application configures (e.g. `Plug.Parsers`' default 8 MB `length:`) and buffers the entire body in memory before the application sees it. An unauthenticated attacker can crash any Bandit-fronted Phoenix/Plug app (BEAM OOM) with a single `Transfer-Encoding: chunked` request to any URL. ### Details In `lib/bandit/http1/socket.ex:189`, the chunked clause of `read_data/2` only forwards `:read_length` and `:read_timeout` to `do_read_chunked_data!/5` (`:242`); the caller-supplied `:length` cap is dropped. The recursion accumulates every chunk into an iolist and `IO.iodata_to_binary/1` (`:196`) materializes the whole thing as one binary. The function always returns `{:ok, body, ...}` — never `{:more, ...}` — so callers cannot interpose a 413. The content-length sibling at `:210` does the right thing: ```elixir max_to_return = min(unread_content_length, Keyword.get(opts, :length, 8_000_000)) ``` Because `Plug.Parsers` runs before routing and auth in the standard Phoenix endpoint, the attacker needs no credentials and no valid route — any `Content-Type` matching a configured parser (`:json`, `:urlencoded`, `:multipart`) on any path triggers the bug. **Suggested Fix:** track accumulated bytes in `do_read_chunked_data!` and either return `{:more, ...}` or raise `request_error!` once `:length` is exceeded, mirroring the content-length path. ### PoC Self-contained — boots a Bandit server with a realistic `Plug.Parsers` (`length: 8_000_000`) and floods it. Save as `chunked_oom.exs`, run `elixir chunked_oom.exs`, and watch `beam.smp` RSS climb past 8 MB until the OS OOM-killer fires. ```elixir Mix.install([{:bandit, "~> 1.10"}, {:plug, "~> 1.19"}]) defmodule DemoApp do use Plug.Builder # The `length` option here is ignored by the attack plug Plug.Parsers, parsers: [:urlencoded, :json], pass: ["*/*"], json_decoder: JSON, length: 8_000_000 plug :respond def respond(conn, _), do: Plug.Conn.send_resp(conn, 200, "ok") end {:ok, _} = Bandit.start_link(plug: DemoApp, ip: {127, 0, 0, 1}, port: 4321) # Builds a single 1MB chunk that is reused on the client-side but accumulated on the server-side. chunk = :binary.copy(< >, 1_048_576) frame = "#{Integer.to_string(1_048_576, 16)}\r\n#{chunk}\r\n" {:ok, sock} = :gen_tcp.connect(~c"127.0.0.1", 4321, [:binary, active: false]) :ok = :gen_tcp.send(sock, """ POST / HTTP/1.1\r Host: 127.0.0.1\r Transfer-Encoding: chunked\r Content-Type: application/json\r Connection: close\r \r """) Enum.each(1..10_240, fn _ -> :ok = :gen_tcp.send(sock, frame) end) :ok = :gen_tcp.send(sock, "0\r\n\r\n") IO.inspect(:gen_tcp.recv(sock, 0, 120_000)) ``` ### Impact Unauthenticated pre-route DoS via BEAM memory exhaustion. One request from one connection crashes the server. Affects every Bandit-fronted application that reads request bodies anywhere — i.e. essentially every Phoenix app, since the default endpoint mounts `Plug.Parsers` ahead of routing and auth. Configured `length:` caps on `Plug.Parsers` and `Plug.Conn.read_body/2` are silently ineffective on the chunked path.

Onderbouwing van de classificatie

Categorie 'supplier_incident' overgenomen van de bron; geen specifieker incidenttype gedetecteerd. Severity 'critical' bepaald op basis van: bronlabel 'high', trefwoord 'unauthenticated'. Confidence 'likely': gerenommeerd securityonderzoek (GitHub Security Advisories). Geen bekende leveranciers of producten herkend.

Kwetsbaarheden

CVE-2026-39803Prioriteitsscore 0.0 / 100
CVSS
EPSS
KEV
Nee
erlang

Gemeentelijke relevantie

35

Deze dreiging scoort 35/100 voor de gemeentelijke relevantie. Meegewogen: een hoge ernstinschaling en een leveranciers- of ketenrisico. Geraakte processen: Netwerk en infrastructuur, Leveranciersketen.

Bestuurlijke duiding

Deze dreiging is relevant voor de gemeente. Omdat het een leverancier betreft, is de gemeente afhankelijk van diens herstel en is regie op de keten nodig. De impact is beheersbaar mits de geadviseerde maatregelen tijdig worden opgevolgd. Laat de CISO de voortgang bewaken en escaleer richting directie zodra nieuwe signalen daartoe aanleiding geven.

Geraakte processen

Netwerk en infrastructuurLeveranciersketen

Geraakte technologie

banditerlang

Betrokken rollen

CISO · ISO · SOC · ICT beheer · Leveranciersmanager

Operationele acties

  • Inventariseer welke koppelingen en gegevensstromen met de leverancier lopen.
  • Schakel waar nodig de koppeling met de leverancier tijdelijk uit.
  • Vraag bewijs van herstel op voordat de dienstverlening wordt hervat.

Concrete stappen voor ICT-beheer en het securityteam.

Aanbevolen acties

  • Breng in kaart welke leveranciers en koppelingen zijn geraakt.
  • Vraag de leverancier om een statusupdate en een herstelplan.
  • Beoordeel de impact op de eigen dienstverlening.

Dit zijn algemene handelingsperspectieven. Stem de opvolging af op de eigen omgeving en het ISMS van uw gemeente.

Kenmerken

Ernst
Kritiek
Categorie
Leveranciersincident
Zekerheid
Waarschijnlijk
Status
Verrijkt
CVE's
CVE-2026-39803
Prioriteitsscore
49 / 100 · Laag
Bron
GitHub Security Advisories
Gepubliceerd
19 mei 2026

Labels

Supply chainOpensource
Originele publicatie