{"id":"CVE-2026-39963","aliases":["GHSA-4m6c-649p-f6gf"],"url":"https://o3.security/vulnerability/CVE-2026-39963","summary":"Serendipity: Host Header Injection enables authentication cookie scoping to an attacker-controlled domain","details":"### Summary\nThe `serendipity_setCookie()` function uses `$_SERVER['HTTP_HOST']` without validation as the `domain` parameter of `setcookie()`. An attacker can force authentication cookies — including session tokens and auto-login tokens — to be scoped to an attacker-controlled domain, facilitating session hijacking.\n\n### Details\nIn `include/functions_config.inc.php:726`:\n```php\nfunction serendipity_setCookie($name, $value, $securebyprot = true, ...) {\n    $host = $_SERVER['HTTP_HOST']; // ← attacker-controlled, no validation\n\n    if ($securebyprot) {\n        if ($pos = strpos($host, \":\")) {\n            $host = substr($host, 0, $pos); // strips port only\n        }\n    }\n\n    setcookie(\"serendipity[$name]\", $value, [\n        'domain'   => $host,   // ← poisoned domain\n        'httponly' => $httpOnly,\n        'samesite' => 'Strict'\n    ]);\n}\n```\n\nThis function is called during login with sensitive cookies:\n```php\n// functions_config.inc.php:455-498\nserendipity_setCookie('author_autologintoken', $rnd, true, false, true);\nserendipity_setCookie('author_username', $user);\nserendipity_setCookie('author_token', $hash);\n```\n\nIf an attacker can influence the `Host` header at login time (e.g. via MITM, reverse proxy misconfiguration, or load balancer), authentication cookies are issued scoped to the attacker's domain instead of the legitimate one.\n\n### PoC\n```bash\ncurl -v -X POST \\\n  -H \"Host: attacker.com\" \\\n  -d \"serendipity[user]=admin&serendipity[pass]=admin\" \\\n  http://[TARGET]/serendipity_admin.php 2>&1 | grep -i \"set-cookie\"\n```\n\nExpected output:\n```http\nSet-Cookie: serendipity[author_token]=; domain=attacker.com; HttpOnly\n```\n\n### Impact\n- **Session fixation** — attacker pre-sets a cookie scoped to their domain, then tricks the victim into authenticating, inheriting the poisoned token\n- **Token leakage** — `author_autologintoken` scoped to wrong domain may be sent to attacker-controlled infrastructure\n- **Privilege escalation** — if admin logs in under a poisoned Host header, their admin token is compromised\n\n### Suggested Fix\nValidate `HTTP_HOST` against the configured `$serendipity['url']` before use:\n```php\nfunction serendipity_setCookie($name, $value, ...) {\n    global $serendipity;\n    $configured = parse_url($serendipity['url'], PHP_URL_HOST);\n    $host = preg_replace('/:[0-9]+$/', '', $_SERVER['HTTP_HOST']);\n    $host = ($host === $configured) ? $host : $configured;\n\n    setcookie(\"serendipity[$name]\", $value, [\n        'domain' => $host,\n        ...\n    ]);\n}\n```","published":"2026-04-14T23:31:13.843Z","modified":"2026-08-12T03:51:28.038516643Z","cvss":{"score":6.9,"severity":"MEDIUM","vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:L/A:N"},"epss":{"score":0.00224,"percentile":0.13243,"asOf":"2026-09-17"},"cisaKev":null,"exploitsKnown":0,"affectedPackages":[{"ecosystem":"Packagist","name":"s9y/serendipity","fixedVersion":"2.6.0"}],"fix":null,"references":[{"type":"WEB","url":"https://github.com/s9y/Serendipity/releases/tag/2.6.0"},{"type":"ADVISORY","url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/39xxx/CVE-2026-39963.json"},{"type":"ADVISORY","url":"https://github.com/s9y/Serendipity/security/advisories/GHSA-4m6c-649p-f6gf"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-39963"},{"type":"PACKAGE","url":"https://github.com/s9y/Serendipity"}],"provenance":{"sources":["OSV.dev","FIRST.org (EPSS)"],"lastVerified":"2026-08-12T03:51:28.038516643Z"}}