GHSA-4M6C-649P-F6GF

Vulnerability from github – Published: 2026-04-14 22:32 – Updated: 2026-04-15 21:14
VLAI?
Summary
Serendipity has a Host Header Injection allows authentication cookie scoping to attacker-controlled domain in functions_config.inc.php
Details

Summary

The 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.

Details

In include/functions_config.inc.php:726:

function serendipity_setCookie($name, $value, $securebyprot = true, ...) {
    $host = $_SERVER['HTTP_HOST']; // ← attacker-controlled, no validation

    if ($securebyprot) {
        if ($pos = strpos($host, ":")) {
            $host = substr($host, 0, $pos); // strips port only
        }
    }

    setcookie("serendipity[$name]", $value, [
        'domain'   => $host,   // ← poisoned domain
        'httponly' => $httpOnly,
        'samesite' => 'Strict'
    ]);
}

This function is called during login with sensitive cookies:

// functions_config.inc.php:455-498
serendipity_setCookie('author_autologintoken', $rnd, true, false, true);
serendipity_setCookie('author_username', $user);
serendipity_setCookie('author_token', $hash);

If 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.

PoC

curl -v -X POST \
  -H "Host: attacker.com" \
  -d "serendipity[user]=admin&serendipity[pass]=admin" \
  http://[TARGET]/serendipity_admin.php 2>&1 | grep -i "set-cookie"

Expected output:

Set-Cookie: serendipity[author_token]=; domain=attacker.com; HttpOnly

Impact

  • Session fixation — attacker pre-sets a cookie scoped to their domain, then tricks the victim into authenticating, inheriting the poisoned token
  • Token leakageauthor_autologintoken scoped to wrong domain may be sent to attacker-controlled infrastructure
  • Privilege escalation — if admin logs in under a poisoned Host header, their admin token is compromised

Suggested Fix

Validate HTTP_HOST against the configured $serendipity['url'] before use:

function serendipity_setCookie($name, $value, ...) {
    global $serendipity;
    $configured = parse_url($serendipity['url'], PHP_URL_HOST);
    $host = preg_replace('/:[0-9]+$/', '', $_SERVER['HTTP_HOST']);
    $host = ($host === $configured) ? $host : $configured;

    setcookie("serendipity[$name]", $value, [
        'domain' => $host,
        ...
    ]);
}
Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "s9y/serendipity"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "2.6.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-39963"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-565"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-04-14T22:32:29Z",
    "nvd_published_at": "2026-04-15T04:17:39Z",
    "severity": "MODERATE"
  },
  "details": "### Summary\nThe `serendipity_setCookie()` function uses `$_SERVER[\u0027HTTP_HOST\u0027]` without validation as the `domain` parameter of `setcookie()`. An attacker can force authentication cookies \u2014 including session tokens and auto-login tokens \u2014 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[\u0027HTTP_HOST\u0027]; // \u2190 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        \u0027domain\u0027   =\u003e $host,   // \u2190 poisoned domain\n        \u0027httponly\u0027 =\u003e $httpOnly,\n        \u0027samesite\u0027 =\u003e \u0027Strict\u0027\n    ]);\n}\n```\n\nThis function is called during login with sensitive cookies:\n```php\n// functions_config.inc.php:455-498\nserendipity_setCookie(\u0027author_autologintoken\u0027, $rnd, true, false, true);\nserendipity_setCookie(\u0027author_username\u0027, $user);\nserendipity_setCookie(\u0027author_token\u0027, $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\u0027s 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\u0026serendipity[pass]=admin\" \\\n  http://[TARGET]/serendipity_admin.php 2\u003e\u00261 | 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** \u2014 attacker pre-sets a cookie scoped to their domain, then tricks the victim into authenticating, inheriting the poisoned token\n- **Token leakage** \u2014 `author_autologintoken` scoped to wrong domain may be sent to attacker-controlled infrastructure\n- **Privilege escalation** \u2014 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[\u0027url\u0027]` before use:\n```php\nfunction serendipity_setCookie($name, $value, ...) {\n    global $serendipity;\n    $configured = parse_url($serendipity[\u0027url\u0027], PHP_URL_HOST);\n    $host = preg_replace(\u0027/:[0-9]+$/\u0027, \u0027\u0027, $_SERVER[\u0027HTTP_HOST\u0027]);\n    $host = ($host === $configured) ? $host : $configured;\n\n    setcookie(\"serendipity[$name]\", $value, [\n        \u0027domain\u0027 =\u003e $host,\n        ...\n    ]);\n}\n```",
  "id": "GHSA-4m6c-649p-f6gf",
  "modified": "2026-04-15T21:14:19Z",
  "published": "2026-04-14T22:32:29Z",
  "references": [
    {
      "type": "WEB",
      "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"
    },
    {
      "type": "WEB",
      "url": "https://github.com/s9y/Serendipity/releases/tag/2.6.0"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:L/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Serendipity has a Host Header Injection allows authentication cookie scoping to attacker-controlled domain in functions_config.inc.php"
}


Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Sightings

Author Source Type Date

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.


Loading…

Detection rules are retrieved from Rulezet.

Loading…

Loading…