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-28695-craft-rce-bypass — Authenticated, **blind** remote code execution in Craft CMS. Fix for CVE-2026-28695 | Kitploit
Tools/GitHubGitHub/gbuyssens/cve-2026-28695-craft-rce-bypass
Vulnerability AnalysisExploitationWeb Application ExploitationPost-ExploitationPenetration TestingRed TeamingRemote Access ToolPayload Development
GitHub
gbuyssens/cve-2026-28695-craft-rce-bypass

CVE-2026-28695-craft-rce-bypass

Authenticated, **blind** remote code execution in Craft CMS. Fix for CVE-2026-28695

View Repository
15 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-28695 patch bypass — Craft CMS ≤ 5.9.8 authenticated RCE (element-search)

CVSS 3.x : 8.8 HIGH   (approx — verify)
CWE      : CWE-502 (Unsafe Object Instantiation) + CWE-1336 (SSTI origin)
Base     : CVE-2026-28695  (SSTI via create() + Symfony Process)
Fix      : advisory fix e31e508 (restricts create() to BaseObject) — BYPASSED here
Affects  : Craft CMS ≤ 5.9.8 with the CVE-2026-28695 fix applied

Authenticated, blind remote code execution in Craft CMS. The official fix for CVE-2026-28695 only restricts create() to yii\base\BaseObject subclasses. The yii\behaviors\AttributeTypecastBehavior gadget is a BaseObject yet still reaches a call_user_func() sink, so it survives the filter. Delivered through the non-Twig admin/actions/element-search/search action, it also side-steps CRAFT_ENABLE_TWIG_SANDBOX. A Content Editor account is enough.


Table of contents

  • Vulnerability summary
  • Why the CVE-2026-28695 PoC is dead on 5.9.8
  • The bypass (gadget chain)
  • The escapeshellcmd constraint
  • Attack chain
  • Affected versions
  • This repository
  • Usage
  • Remediation
  • References

Vulnerability summary

Craft's element-search controller deserialises attacker JSON into live PHP objects via Yii's Craft::createObject() / Instance machinery. By attaching an AttributeTypecastBehavior whose attributeTypes maps an attribute to the callable [Psy\Readline\Hoa\ConsoleProcessus, execute] and firing the beforeSave event, the typecast becomes:

call_user_func([Psy\Readline\Hoa\ConsoleProcessus, "execute"], "<CMD>")

The endpoint always answers HTTP 500 and returns no command output — execution is blind.


Why the CVE-2026-28695 PoC is dead on 5.9.8

  • CVE-2026-28695 = SSTI via create() + Symfony Process, reached from a Twig sink (typically Entry Types → Title Format).
  • On 5.9.8 the fix commit e31e508 restricts create() to BaseObject subclasses, and the target also runs with CRAFT_ALLOW_ADMIN_CHANGES=false (settings → 403) and CRAFT_ENABLE_TWIG_SANDBOX=true. The documented vector is triple-closed.
  • Lesson: confront the exact version against the fix commit, don't fire on the CVE name. Here the fix is older than the deployed build → look for a filter bypass, not the raw PoC.

The bypass (gadget chain)

yii\behaviors\AttributeTypecastBehavior  ->  Psy\Readline\Hoa\ConsoleProcessus::execute

Double bypass, by construction:

  1. Sandbox — element-search is a PHP object path, not a Twig render. CRAFT_ENABLE_TWIG_SANDBOX only gates the template engine, so it never applies.
  2. Patch — the fix restricts create() to BaseObject. AttributeTypecastBehavior → yii\base\Behavior → yii\base\BaseObject, so it satisfies the new constraint while still offering an execution sink. The fix closes one family of classes, not the BaseObject class.

Endpoint:

POST /index.php?p=admin/actions/element-search/search
X-CSRF-Token: <dashboard csrf>
X-Requested-With: XMLHttpRequest
Accept: application/json

The escapeshellcmd constraint

Hoa\ConsoleProcessus::execute() runs the command through escapeshellcmd():

  • Neutralised: | && ; > < $() ' " → no chaining, no pipes, no redirection, no classic bash reverse shell.
  • Passes through: : , /
  • Result: one binary + arguments, no shell metacharacters.

This is why the payload is a single socat TCP-LISTEN,fork EXEC bind shell (args in : / , / /) rather than a reverse shell.


Attack chain

   Attacker (Content Editor)                Craft CMS 5.9.8
        |                                        |
        |  GET /admin/login  (scrape CSRF)       |
        |--------------------------------------->|
        |  POST users/login (jenny:******)       |
        |--------------------------------------->|
        |  GET /admin/dashboard (JS csrf)        |
        |<---------------------------------------|
        |  POST element-search/search            |
        |    AttributeTypecastBehavior gadget    |
        |    typecastBeforeSave = "<CMD>"        |
        |--------------------------------------->|  call_user_func(
        |  HTTP 500  (blind, no output)          |    [ConsoleProcessus,execute], CMD)
        |<---------------------------------------|  -> escapeshellcmd(CMD) -> exec
        |                                        |
        |  oracle: "sleep 5" -> +~5s latency     |
        |  shell:  socat TCP-LISTEN:4445 bind     |

Affected versions

StatusVersions
VulnerableCraft CMS ≤ 5.9.8 with the CVE-2026-28695 fix
NoteThe gadget requires an authenticated CP session

This repository

FileRole
exploit.pyPoC: login → timing-oracle check → single cmd → bind shell
README.mdThis file

Usage

Requires requests (pip install requests).

# 1. Prove code execution (timing oracle: sleep 5 must add ~5s)
python3 exploit.py http://example.lab --check

# 2. Fire a single blind command (one binary + args, no metachars)
python3 exploit.py http://example.lab "sleep 5"

# 3. Plant a persistent bind shell as the web user, then connect
python3 exploit.py http://example.lab --bind 4445
nc IP or exemple.lab 4445

# custom creds
python3 exploit.py http://exemple.lab -u User -p 'SecureP4$$!' --bind

What happens:

  1. Scrape the login CSRF, authenticate to the CP, pull the dashboard action CSRF.
  2. Send the AttributeTypecastBehavior gadget to element-search.
  3. --check proves blind exec by injected latency; --bind drops a socat listener.

Remediation

  1. Upgrade Craft CMS to a release that constrains object instantiation on all deserialised input paths (not just create()), and audit element-search condition handling.
  2. Keep CRAFT_ALLOW_ADMIN_CHANGES=false and minimise Content Editor privileges — auth is the only precondition here.
  3. Remove/upgrade the bundled psy/psysh (Hoa) dependency where a ConsoleProcessus::execute gadget is reachable.
  4. WAF/telemetry: alert on element-search/search bodies containing __class, as rce, or AttributeTypecastBehavior; flag bursts of HTTP 500 from that action.

References

  • NVD — CVE-2026-28695 (base SSTI)
  • Craft CMS fix commit e31e508 (create() → BaseObject restriction)
  • Yii AttributeTypecastBehavior / yii\base\Security docs

Disclaimer

This project is for authorized security testing, education, and defensive research only. You are responsible for complying with applicable laws and the rules of engagement of your lab or client.

Download Tool