Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

FeedsContactPrivacy© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
cve-2026-100671-poc — Local-only proof-of-concept verifier for CVE-2026-100671, reproducing Grav Twig page-cache session-cookie disclosure and replay against loopback targets. | Kitploit
Tools/GitHubGitHub/canhieu/cve-2026-100671-poc
Vulnerability AnalysisExploitationWeb Application ExploitationSecurity VirtualizationWeb SecurityPenetration Testing
GitHubcanhieu/cve-2026-100671-poc

cve-2026-100671-poc

Local-only proof-of-concept verifier for CVE-2026-100671, reproducing Grav Twig page-cache session-cookie disclosure and replay against loopback targets.

View Repository
2322 days agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2026-100671 — Grav Twig session-cookie disclosure

Minimal, target-scoped attacker-side verifier for the Grav content-Twig/page-cache session takeover fixed in Grav 2.0.25.

Advisories:

  • CVE-2026-100671
  • GHSA-pp89-h475-7gj6
  • Grav 2.0.25 release

Important: no administrator credential

The attacker does not have the administrator username or password.

The real chain is:

  1. A low-privilege page writer publishes the Twig payload.
  2. An administrator visits the public page once.
  3. The attacker requests the same page anonymously.
  4. The shared page cache returns the administrator session cookie.
  5. The attacker replays that cookie against the API.

The administrator action happens outside this script. exploit.py accepts no GRAV_ADMIN_USERNAME or GRAV_ADMIN_PASSWORD setting.

Scope

Loopback is the default safety boundary. A non-loopback target requires the explicit --allow-remote flag, intended for an authorized HTB, TryHackMe, or owned lab machine.

The client follows redirects only when they stay on the selected target origin, uses Python standard-library HTTP clients, applies request timeouts, and prints the captured cookie only when --show-cookie is explicitly supplied.

Use only against a Grav instance that you own or are explicitly authorized to test. The script creates a public proof page. Remove that page after testing if the target keeps content between runs.

Vulnerability chain

  1. A low-privilege page writer publishes content containing sandboxed Twig.
  2. get_cookie() reads the visiting administrator's session cookie server-side.
  3. Grav stores post-Twig page output in a cache without session identity.
  4. An unauthenticated request receives the cached cookie name and value.
  5. Replaying that value against the target API authenticates as the administrator.

The page-write account needs only the low-privilege write path. It does not need api.pages.read, admin.*, super-admin access, or administrator credentials.

Affected versions

  • Grav 2.0.19 through 2.0.24: vulnerable with shipped default content-Twig configuration.
  • Grav 2.0.0 through 2.0.18, and 1.7.x: affected only when content Twig was explicitly enabled.
  • Grav 2.0.25: fixed.

Lab requirements

Run a Grav target with:

  • Grav API plugin enabled;
  • one low-privilege writer account able to obtain an API token and create pages;
  • one administrator account for the victim action;
  • the target page route publicly readable.

This two-file repository does not provision Grav, PHP, plugins, accounts, or an administrator bot. The victim visit remains an external action.

One-shot interactive run

Set only the low-privilege writer credential or token:

export GRAV_TARGET=http://127.0.0.1:8080
export GRAV_WRITER_USERNAME=low
export GRAV_WRITER_PASSWORD='local-writer-password'

python3 exploit.py

The script creates a random public route, prints its URL, and waits. Have the administrator visit that URL once, then press Enter. The script performs the anonymous collection and local API replay.

Use an existing writer API token instead:

export GRAV_WRITER_TOKEN='local-low-privilege-token'
python3 exploit.py

Two-phase run

Useful for a non-interactive terminal or a separate victim browser.

Prepare the page:

python3 exploit.py --prepare-only

Have an administrator visit the printed URL. Then collect and replay using the printed route; no credential is needed for this second phase:

python3 exploit.py --collect-only --route /cookie-proof-XXXXXXXX --show-cookie

--show-cookie prints the captured session cookie for local/authorized lab debugging:

captured_cookie=grav-site-<hash>=<session-value>

The value is a live credential. Do not paste it into GitHub, issues, chat, screenshots, or logs. Without --show-cookie, the script proves the same impact through the replay status while keeping the value out of output.

If collection runs before the administrator visit, the attacker request may populate the cache with an empty value. Prepare a new random route and repeat.

Do not hardcode a machine IP in the repository. Supply the current target at runtime:

export GRAV_WRITER_USERNAME=low
export GRAV_WRITER_PASSWORD='writer-password'

python3 exploit.py \
  --target http://10.10.10.25:8080 \
  --allow-remote \
  --prepare-only

After the administrator/bot visits the printed URL, collect and replay:

python3 exploit.py \
  --target http://10.10.10.25:8080 \
  --allow-remote \
  --collect-only \
  --route /cookie-proof-XXXXXXXX \
  --show-cookie

--base-url remains a compatibility alias for --target. Remote HTTP prints a cleartext warning; use HTTPS where the machine supports it.

Expected vulnerable result

page_create_status=201
victim_action_url=http://127.0.0.1:8080/cookie-proof-XXXXXXXX
anonymous_page_status=200
cookie_name_disclosed=yes
cached_cookie_visible_to_attacker=yes
captured_cookie=grav-site-<hash>=<session-value>
replayed_cookie_api_status=200
result=VULNERABLE

The captured_cookie line appears only with --show-cookie.

Fixed-version check

Run the same two-phase flow against Grav 2.0.25 or later, then collect with:

python3 exploit.py --collect-only --route /cookie-proof-XXXXXXXX --expect fixed

Expected fixed behavior: no attacker-visible session value and no successful session replay. A clean fixed result exits 0 with --expect fixed.

Remediation

Upgrade to Grav 2.0.25 or later. For older deployments, the advisory lists these temporary controls:

  • disable content Twig with security.twig_content.process_enabled: false; or
  • set system.pages.never_cache_twig: true;
  • clear existing Grav caches;
  • rotate administrator sessions.

Do not treat HttpOnly, Secure, or SameSite as a fix: the vulnerable cookie read occurs server-side during Twig rendering.

Disclosure

Reported by canhieu. This repository is a reproducibility aid for the already-public advisory, not a remote scanner or a credential-harvesting tool.

Download Tool