HexBrain

curl · Report #3463608

Denial of Service (DoS) vulnerability in dedotdotify() URL path normalization

N/Astatus
highseverity
13upvotes
13 Dec 2025disclosed

How it was found

Summary

A Denial of Service (DoS) vulnerability exists in the dedotdotify() function in lib/urlapi.c that can cause excessive CPU consumption due to O(n²) time complexity when processing URLs with malicious path patterns containing many ../ sequences.

Affected Component

  • Component: libcurl URL API
  • File: lib/urlapi.c
  • Function: dedotdotify() (lines 794-898)
  • Vulnerable Code: Lines 857-866

Vulnerability Details

The dedotdotify() function normalizes URL paths by removing ../ and ./ sequences according to RFC 3986 Section 5.2.4. However, the implementation has a quadratic time complexity (O(n²)) vulnerability.

Root Cause

When processing a /../ sequence, the code uses memrchr() to find the last / in the output buffer to remove the preceding segment:

else if(is_dot(&p, &blen) && (ISSLASH(*p) || !blen)) {
  /* remove the last segment from the output buffer */
  size_t len = curlx_dyn_len(&out);
  if(len) {
    char *ptr = curlx_dyn_ptr(&out);
    char *last = memrchr(ptr, '/', len);  // O(n) operation
    if(last)
      curlx_dyn_setlen(&out, last - ptr);
  }

Each memrchr() call scans the entire current output buffer length, which is O(n). When processing a path like /a1/a2/.../an/../.., the function:

  1. First adds all n segments to the output buffer (buffer size grows to ~n segments)
  2. For each /../, calls memrchr() which scans the entire remaining buffer
  3. Total operations: O(n + (n-1) + (n-2) + ... + 1) = O(n²)

Attack Vector

This vulnerability is triggered in all normal URL parsing operations:

  1. Command-line curl: When processing user-provided URLs

    • Code path: src/tool_operate.c → parseurlandfillconn() → curl_url_set()
  2. libcurl API: When CURLOPT_URL is set

    • Code path: lib/url.c:1771 → curl_url_set() → parseurl() → dedotdotify()
  3. Default behavior: Triggered when CURLU_PATH_AS_IS flag is not set (default)

    • Check: lib/urlapi.c:1230-1233

Input Size Limit

  • Maximum input length: CURL_MAX_INPUT_LENGTH = 8MB (8,000,000 bytes)
  • An attacker can create paths up to this limit to maximize CPU consumption

Impact

Severity Assessment

CVSS v3.1 Vector: AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

  • Attack Vector: Network (malicious URL can be provided via HTTP request, redirect, etc.)
  • Attack Complexity: Low (simple URL manipulation)
  • Privileges Required: None
  • User Interaction: None
  • Scope: Unchanged
  • Confidentiality: None
  • Integrity: None
  • Availability: High (CPU exhaustion leading to DoS)

Affected Scenarios

  1. Web servers/proxies that process user-provided URLs using curl/libcurl
  2. API clients that accept external URLs
  3. Mobile applications processing URLs from user input or network responses
  4. Any application using curl/libcurl to parse URLs from untrusted sources

Potential Consequences

  • CPU exhaustion: High CPU usage for extended periods
  • Service degradation: Delayed response to legitimate requests
  • Resource starvation: May prevent other requests from being processed
  • Amplification: A single malicious URL can consume significant CPU resources

Proof of Concept

Malicious URL Pattern

http://example.com/a1/a2/a3/.../an/../../

This pattern first adds n path segments, then processes n ../ sequences, causing maximum CPU consumption.

PoC Code

A complete proof-of-concept is provided in dos_PoC.c:

// Compile: gcc -o dos_PoC dos_PoC.c -lcurl
// Run: ./dos_PoC

Performance Measurements

Testing results on macOS with optimized build:

SegmentsPath LengthProcessing TimeTime Ratio
100690 bytes0.000012s1.0x
1,0007,890 bytes0.000028s2.3x
10,00088,890 bytes0.000271s22.6x
50,000488,890 bytes0.001383s115.3x

Analysis:

  • When input size increases 10x (1,000 → 10,000 segments), processing time increases ~9.7x
  • This demonstrates quadratic time complexity (approaching O(n²))
  • With maximum allowed input (8MB), the impact would be significantly greater

Steps to Reproduce

  1. Compile the PoC:

    gcc -O2 -o dos_PoC dos_PoC.c -lcurl
    
  2. Run the PoC:

    ./dos_PoC
    
  3. Observe the processing time increases quadratically with input size.

  4. Test with actual curl command:

    # Create malicious URL
    MALICIOUS_URL="http://example.com$(python3 -c "print('/a' + '/a'.join(map(str, range(10000))) + '/../' * 10000)")"
    
    # Measure time
    time curl "$MALICIOUS_URL"
    

Affected Versions

This vulnerability affects all versions of curl/libcurl that include the dedotdotify() function. The function was introduced as part of the URL API implementation.

The vulnerability exists in the current codebase at:

  • File: lib/urlapi.c
  • Function: dedotdotify() (line 794)

Recommended Mitigation

Short-term Workaround

Applications can use the CURLU_PATH_AS_IS flag to skip path normalization:

  • For curl_url_set(): Pass CURLU_PATH_AS_IS in flags
  • For CURLOPT_URL: Use CURLOPT_PATH_AS_IS option

Note: This workaround may have security implications if path normalization is required for security purposes.

Long-term Fix

The dedotdotify() function should be rewritten to achieve O(n) time complexity:

  1. Track last slash position: Instead of using memrchr() to search for the last / each time, maintain a pointer or index to the last segment boundary.

  2. Single-pass algorithm: Process the path in a single pass, maintaining a stack or pointer array of segment boundaries.

  3. Example approach:

    • Use a linked list or array to track segment boundaries
    • When encountering ../, pop from the segment stack instead of searching
    • This reduces complexity from O(n²) to O(n)

Input Validation

Consider adding path length limits specifically for dedotdotify() processing, independent of the overall CURL_MAX_INPUT_LENGTH limit.

Additional Information

Related Code References

  • Vulnerability location: lib/urlapi.c:857-866
  • Function definition: lib/urlapi.c:794-898
  • Call site: lib/urlapi.c:1230-1233
  • URL parsing entry point: lib/urlapi.c:901 (parseurl())

Testing Environment

  • OS: macOS (darwin 25.1.0)
  • Compiler: gcc with -O2 optimization
  • curl: Latest source code from repository

Disclosure

This vulnerability was discovered through source code analysis and verified with proof-of-concept code. No actual exploitation attempts were made against production systems.

References


Reporter

  • Jiyong Yang / BAEKSEOK University

Impact

An attacker can cause denial of service and excessive CPU consumption by providing a malicious URL with a path containing many ../ sequences. The dedotdotify() function processes such paths with O(n²) time complexity, consuming disproportionate CPU resources and potentially rendering the service unresponsive or significantly degraded. This affects any application using curl/libcurl to parse untrusted URLs, including web servers, proxies, API clients, and mobile applications.

This report was disclosed publicly on HackerOne and belongs to its author and the program. See the original