curl · Report #3463608
Denial of Service (DoS) vulnerability in dedotdotify() URL path normalization
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:
- First adds all n segments to the output buffer (buffer size grows to ~n segments)
- For each
/../, callsmemrchr()which scans the entire remaining buffer - Total operations: O(n + (n-1) + (n-2) + ... + 1) = O(n²)
Attack Vector
This vulnerability is triggered in all normal URL parsing operations:
-
Command-line curl: When processing user-provided URLs
- Code path:
src/tool_operate.c→parseurlandfillconn()→curl_url_set()
- Code path:
-
libcurl API: When
CURLOPT_URLis set- Code path:
lib/url.c:1771→curl_url_set()→parseurl()→dedotdotify()
- Code path:
-
Default behavior: Triggered when
CURLU_PATH_AS_ISflag is not set (default)- Check:
lib/urlapi.c:1230-1233
- Check:
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
- Web servers/proxies that process user-provided URLs using curl/libcurl
- API clients that accept external URLs
- Mobile applications processing URLs from user input or network responses
- 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:
| Segments | Path Length | Processing Time | Time Ratio |
|---|---|---|---|
| 100 | 690 bytes | 0.000012s | 1.0x |
| 1,000 | 7,890 bytes | 0.000028s | 2.3x |
| 10,000 | 88,890 bytes | 0.000271s | 22.6x |
| 50,000 | 488,890 bytes | 0.001383s | 115.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
-
Compile the PoC:
gcc -O2 -o dos_PoC dos_PoC.c -lcurl -
Run the PoC:
./dos_PoC -
Observe the processing time increases quadratically with input size.
-
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(): PassCURLU_PATH_AS_ISin flags - For
CURLOPT_URL: UseCURLOPT_PATH_AS_ISoption
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:
-
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. -
Single-pass algorithm: Process the path in a single pass, maintaining a stack or pointer array of segment boundaries.
-
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
- RFC 3986 Section 5.2.4: "Remove Dot Segments"
- curl Security Policy: https://curl.se/docs/security.html
- curl Vulnerability Disclosure Policy: https://curl.se/dev/vuln.html
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.