top of page

CVE-2025-13654: Stack Buffer Overflow in Duc via Integer Underflow

  • Hacking By Doing
  • 4 days ago
  • 2 min read

Updated: 25 minutes ago

ree

Date: December 05, 2025

Author: HackingByDoing

Product: Duc

CVSS: High (DoS / Information Disclosure)


While auditing Duc, a popular tool available in the official Debian repositories for indexing, inspecting, and visualizing disk usage, I discovered a stack-based buffer overflow vulnerability within the libduc library.


This vulnerability, caused by a classic unsigned integer underflow, has been assigned CVE-2025-13654. Below is the technical breakdown of the discovery, the root cause analysis, and the disclosure timeline with CERT/CC.


The Vulnerability

The issue lies within the buffer_get function in src/libduc/buffer.c. This function is responsible for reading data from a buffer structure. It attempts to perform a bounds check before copying data, but the logic is flawed due to the use of size_t (an unsigned type).


Here is the vulnerable code snippet:

static int buffer_get(struct buffer *b, void *data, size_t len)
{
    /* UNSAFE: size_t underflow when len > b->len */
    if (b->ptr <= b->len - len) {
        memcpy(data, b->data + b->ptr, len);
        b->ptr += len;
        return len;
    }
    return 0;
}

The Root Cause: Unsigned Underflow

The sanity check if (b->ptr <= b->len - len) is dangerous.


Because len and b->len are size_t (unsigned integers), if an attacker requests a read length (len) that is greater than the remaining buffer length (b->len), the subtraction b->len - len does not result in a negative number. Instead, it wraps around (underflows) to a massive positive integer.


Consequently, the check evaluates to true, bypassing the safety mechanism. The program then executes memcpy, reading adjacent memory on the stack beyond the bounds of the allocated buffer.


Exploitation & Impact

To confirm this, I wrote a small PoC harness that links against libduc. I compiled it using Clang with AddressSanitizer enabled.


The PoC sets up a tiny 3-byte buffer but requests to read 255 bytes:

/* Simplified PoC */
uint8_t raw[3] = {0xFF, 'A', 'B'};
struct buffer *b = buffer_new(raw, sizeof raw);
uint8_t *dst = malloc(255);

/* Trigger: Request 255 bytes from a 3-byte buffer */
buffer_get(b, dst, 255);

Running this resulted in an immediate ASan crash:


ree

Impact:


  1. Denial of Service (DoS): The out-of-bounds read can crash the application processing the malicious input.


  2. Information Disclosure: An attacker could potentially read sensitive data from the stack adjacent to the buffer.


The Fix

The fix is straightforward. Instead of subtracting (which risks underflow), you should add the requested length to the current pointer and check if it exceeds the total buffer size.

if (b->ptr + len <= b->len) {
    memcpy(data, b->data + b->ptr, len);
    // ...
}

Disclosure Timeline

The vulnerability was coordinated through CERT/CC (VINCE).

  • 2025-10-08: Vulnerability reported to CERT/CC.

  • 2025-11-06: CERT reaches out to the vendor. The vendor responds that a patch is applied and version 1.4.6 is released.

  • 2025-11-25: CERT/CC confirmed the fix was properly applied in the 1.4.6 release and assigned CVE-2025-13654.

  • 2025-12-05: Public Disclosure.


Conclusion

This is a textbook example of why integer arithmetic with size_t requires extra care in C. Always validate bounds by adding and comparing against the maximum limit, rather than subtracting and hoping you don't wrap around.


Users of duc should upgrade to version 1.4.6 immediately.


Thanks to CERT/CC for handling the coordination.



 
 
bottom of page