TinyWeb Buffer Overflow DoS (CVE-2024-34199)

Security Advisory. Published: 2024-05-14. Fixed in TinyWeb v1.99.

Summary

TinyWeb HTTP Server version 1.94 and below is vulnerable to a heap-based buffer overflow that allows unauthenticated remote attackers to cause a complete denial of service. The TCollector.Collect() function in SrvMain.pas grows an internal buffer without bounds when parsing HTTP request lines, enabling an attacker to crash the server by sending a single oversized request without CRLF termination.

Severity: High (CVSS 3.1 Base Score: 8.6)

Vulnerability Details

CVE ID CVE-2024-34199
GHSA ID GHSA-wx4f-9wf4-26p4
Vulnerability Type Heap-based Buffer Overflow (CWE-787, CWE-122)
Attack Type Remote, Unauthenticated
Attack Vector Network (single TCP connection)
Original Vendor RITLABS S.R.L.
Current Maintainer Maxim Masiutin
Product TinyWeb HTTP Server
Affected Versions 1.94 and below (all versions from 0.5 through 1.98)
Fixed Version 1.99 (January 5, 2026)
Affected Component TCollector.Collect() in SrvMain.pas
Impact Complete Denial of Service (server crash, memory exhaustion)

CVSS Scores

CVSS Version Score Severity Vector String
CVSS 3.1 (CISA-ADP) 8.6 High AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:H
EPSS 1.916% 83rd percentile Probability of exploitation in the wild within 30 days

Background

TinyWeb HTTP Server was originally developed by RITLABS S.R.L. (Moldova) in 1997 as a minimal Windows HTTP server -- no GUI, no console window, no Windows Service; it runs as a silent background process. The last RITLABS release was v1.94 (April 2017). In 2021, Maxim Masiutin took over open-source maintenance on GitHub. The server is written in Object Pascal (compiles with both Delphi and Free Pascal) and produces a single ~60KB executable. Its small footprint and simplicity made it popular for lightweight deployments, but also meant limited security hardening of the HTTP parser.

This vulnerability existed in the original RITLABS code since at least version 0.5 (1997). The TCollector class was designed for efficiency -- it accumulates bytes until a CRLF delimiter is found -- but never anticipated adversarial input that omits CRLF entirely. The 32-bit architecture makes the attack particularly effective: the ~2GB address space limit is reachable with a single ~897MB payload.

DMCERTCE reported both this vulnerability and CVE-2024-5193 (CRLF injection) in May 2024. According to VulDB, the original vendor RITLABS did not respond to disclosure attempts. The fix was implemented by the current maintainer in January 2026.

Technical Details

Root Cause

The HTTP request parser in TinyWeb uses a TCollector class to accumulate incoming bytes into lines delimited by CRLF (\r\n). The Collect() method stores each incoming byte into an internal CollectStr buffer, growing it via SetLength() as needed. Prior to version 1.99, there were no upper bounds on the buffer size or total header size.

TinyWeb is a 32-bit Windows application with a maximum virtual address space of approximately 2GB. An attacker who sends continuous data without a CRLF terminator forces the buffer to grow indefinitely until the heap is exhausted, triggering a runtime error 203 (heap overflow) that crashes the handler thread and leaks its memory.

Attack Mechanism

  1. Attacker opens a TCP connection to the TinyWeb server
  2. Attacker sends a continuous stream of bytes (e.g., 'P' * 941114855 = ~897MB) without any CRLF sequence
  3. TCollector.Collect() stores every byte, growing CollectStr via SetLength(): 1KB, 2KB, 4KB, ... up to 2GB
  4. No CRLF means the line never completes and the buffer never resets
  5. The 32-bit process hits its address space limit; the handler thread crashes with runtime error 203
  6. The crashed thread leaks all allocated memory in the main server process
  7. Repeating the attack a few times exhausts available memory and crashes the server entirely

Vulnerable Code (SrvMain.pas, before fix)

Before the fix, the inner loop of TCollector.Collect() had no bounds checks:

for i := 0 to j - 1 do
begin
  if l <= CollectLen then
  begin
    Inc(l, j + 100);
    SetLength(CollectStr, l);   // Unbounded growth!
  end;
  Inc(CollectLen);
  CollectStr[CollectLen] := Buf[i];
  // ... CRLF detection ...
end;

Exploitation Requirements

  • TinyWeb version 1.98 or earlier
  • Network access to the TinyWeb server (TCP)
  • No authentication required
  • Single TCP connection sufficient to crash one thread
  • A few repeated connections crash the entire server

Proof of Concept Analysis

A proof-of-concept Python script (Tiny_PoC.py) was published on May 12, 2024 by security researcher DMCERTCE at github.com/DMCERTCE/PoC_Tiny_Overflow. DMCERTCE also discovered and published the PoC for CVE-2024-5193 (CRLF injection in TinyWeb).

PoC Script Behavior

  1. Target validation: Sends an HTTP GET request via requests.get() and checks that the Server response header equals TinyWeb/1.94. Exits if the target is not TinyWeb.
  2. Non-blocking socket: Opens a raw TCP socket with setblocking(0) to avoid blocking on send when the server's receive buffer fills up.
  3. Payload delivery: Sends 941,114,855 bytes (~897MB) of the character 'P' in 1KB chunks. No CRLF (\r\n) is ever sent, so TinyWeb's TCollector.Collect() never completes parsing a line and the buffer grows without bound.
  4. Timeout detection: When the server's TCP receive window closes (kernel buffer full), the non-blocking send raises BlockingIOError. After 15 seconds of continuous failure, the script considers that thread overloaded.
  5. Late HTTP framing: After the payload, the script sends " / HTTP/1.1\r\nHost: ...\r\n\r\n", but by this point the buffer has already overflowed and the thread has crashed with runtime error 203.
  6. Liveness check: Polls the server with requests.get() every 5 seconds. If the server returns HTTP 200, the attack loop repeats. Each iteration crashes one handler thread and leaks its memory.
  7. Termination: When the server stops responding (all memory exhausted), prints "Server Dead" and exits.

Why the Attack Works

The key insight is that TinyWeb's HTTP parser reads bytes into a Delphi/FPC AnsiString buffer using SetLength() to grow it. Free Pascal's heap manager doubles the allocation on each resize, so the memory consumption follows an exponential growth pattern: 1KB, 2KB, 4KB, ... up to the 2GB address space limit of a 32-bit process. A single connection sending ~897MB of raw data is sufficient to trigger the overflow. The 32-bit address space limit is the critical constraint -- a 64-bit build would require far more data but would still be vulnerable in principle.

Each crashed thread leaks its entire heap allocation because the thread terminates abnormally (runtime error 203) and the main process never reclaims the memory. After 2-3 attack cycles, the main process itself runs out of address space and crashes.

PoC Output

$ python Tiny_PoC.py 192.168.1.100 80
Server validated as TinyWeb server, sending malformed request...
Overload Sent - Next Cycle
Server is still up and responding.
Overload Sent - Next Cycle
Server Dead - Good Job!

Minimal Reproduction

The vulnerability can also be triggered with a one-liner (no PoC script needed):

# Send ~1GB of 'A' bytes without CRLF to crash one thread
python -c "import socket;s=socket.socket();s.connect(('TARGET',80));s.send(b'A'*1000000000)"

Fix Applied in Version 1.99

Version 1.99 adds two constants defining maximum header sizes and checks them on every byte received.

Constants (SrvMain.pas)

CMaxHeaderLineLength = 8192;   // CVE-2024-34199: Max 8KB per request line
CMaxTotalHeaderSize = 65536;   // CVE-2024-34199: Max 64KB total headers

Bounds Checks in TCollector.Collect() (SrvMain.pas)

for i := 0 to j - 1 do
begin
  // CVE-2024-34199: Check for excessive line length
  if CollectLen >= CMaxHeaderLineLength then
  begin
    Result := False;
    Exit;
  end;
  // CVE-2024-34199: Check for excessive total header size
  if TotalSize >= CMaxTotalHeaderSize then
  begin
    Result := False;
    Exit;
  end;

  if l <= CollectLen then
  begin
    Inc(l, j + 100);
    // CVE-2024-34199: Cap allocation at max line length
    if l > CMaxHeaderLineLength then
      l := CMaxHeaderLineLength;
    SetLength(CollectStr, l);
  end;
  Inc(CollectLen);
  Inc(TotalSize);
  CollectStr[CollectLen] := Buf[i];
  // ... CRLF detection ...
end;

When either limit is exceeded, Collect() returns False, causing the server to immediately reject the connection. The buffer allocation is also capped at CMaxHeaderLineLength, preventing any single allocation from exceeding 8KB.

Limit Rationale

The chosen limits align with industry standards: Apache httpd defaults to 8190 bytes per request line (LimitRequestLine), nginx defaults to 8KB for header buffers (large_client_header_buffers), and IIS defaults to 16KB. The 64KB total header limit matches Apache's LimitRequestFieldSize defaults. RFC 9110 Section 4.1 recommends servers handle at least 8000 octets in a request line. No legitimate HTTP client sends request lines exceeding these bounds.

Mitigation

Recommended: Upgrade to TinyWeb version 1.99 or later.

Workaround: If upgrade is not immediately possible:

  • Place TinyWeb behind a reverse proxy (nginx, Apache, IIS ARR) that enforces request line length limits. Most reverse proxies reject oversized request lines by default (e.g., nginx large_client_header_buffers defaults to 8KB).
  • Use a network-level rate limiter or firewall to restrict connection bandwidth and concurrent connections per IP.
  • There is no configuration option within TinyWeb itself to set header size limits without upgrading.

Timeline

2024-05-12 Proof of concept published on GitHub by DMCERTCE
2024-05-14 CVE-2024-34199 published by MITRE
2024-05-22 NVD entry created
2026-01-05 Fix implemented by current maintainer (Maxim Masiutin)
2026-01-05 TinyWeb v1.99 released with fix

Credit

Vulnerability Discovery and PoC: DMCERTCE (security researcher). Published both CVE-2024-34199 (buffer overflow) and CVE-2024-5193 (CRLF injection) proof-of-concept exploits for TinyWeb on May 12, 2024. The PoC repository includes Tiny_PoC.py, a Python script demonstrating complete server denial of service via heap exhaustion.

CVE Assignment: MITRE (CNA). Published CVE-2024-34199 on May 14, 2024.

CVSS Assessment: CISA-ADP assigned the CVSS 3.1 score of 8.6 (High).

Fix Implementation: Maxim Masiutin (current open-source maintainer of TinyWeb since 2021; original vendor RITLABS S.R.L. is no longer maintaining the product). Fix committed January 5, 2026, released as TinyWeb v1.99.

References

Other TinyWeb CVEs

CVE-2024-5193 CRLF Injection (CWE-93) - Fixed in v1.99. CVSS 5.0 Medium. Advisory
CVE-2026-22781 Command Injection (CWE-78) - Fixed in v1.98. CVSS 9.8 Critical. Advisory
CVE-2004-2636 Path Traversal (CWE-22) - Fixed in v1.93. CVSS 5.0 Medium. Advisory
CVE-2003-1510 Denial of Service (CWE-400) - Fixed in v1.93. CVSS 7.8 High. Advisory