eness/php2shell-CVE-2026-109618-CVE-2026-109619-PoC

★ 1,043⑂ 262

Proof-of-Concept (PoC) exploit for php2shell (CVE-2026-109618 / CVE-2026-109619), demonstrating remote code execution in vulnerable PHP environments.

About eness/php2shell-CVE-2026-109618-CVE-2026-109619-PoC

eness/php2shell-CVE-2026-109618-CVE-2026-109619-PoC is an open-source project on GitHub, mainly written in Shell. Proof-of-Concept (PoC) exploit for php2shell (CVE-2026-109618 / CVE-2026-109619), demonstrating remote code execution in vulnerable PHP environments. It currently holds 1,043 stars and 262 forks with 0 open issues, and was last pushed on an unknown date (repository created unknown).

Project Overview

Git Homed tracks it on the Today's Trending board.

GitHub Repository Details

Repository eness/php2shell-CVE-2026-109618-CVE-2026-109619-PoC · default branch - · size 0 KB · watchers 0 · source: GitHub REST API and repository README

README

https://github.com/eness/php2shell-CVE-2026-109618-CVE-2026-109619-PoC/blob/HEAD/php2shell — CVE-2026-109618 / CVE-2026-109619

php2shell — CVE-2026-109618 / CVE-2026-109619

Critical Advisory (CVSS v4.0: 9.2 - Critical): On October 20, details of two pre-auth Remote Code Execution (RCE) flaws in the PHP core leaked online ahead of coordinated disclosure. Exploitation allows arbitrary command execution straight from the web server.

---

Table of Contents

---

Overview

php2shell refers to two critical vulnerabilities (CVE-2026-109618 & CVE-2026-109619) affecting core PHP functionality. The primary demonstrated vector is a heap use-after-free (UAF) in the PHP core session upload progress mechanism leading to arbitrary code execution (zend_call_function / system()).

Root Cause

PHP's upload progress handler (php_session_rfc1867_callback in ext/session/session.c) stores two raw zval * bucket pointers (post_bytes_processed and current_file_bytes_processed) directly in live HashTable structures.

During request processing: 1. Trigger: A standard multipart POST request activates progress tracking with default configuration values (session.upload_progress.enabled = 1). 2. Free: A progress update cycle re-reads session data. The function zend_hash_update() destroys the previous data tree using the destructor zval_ptr_dtor, freeing the memory block. 3. Reclaim: The freed bucket memory is reclaimed. The dangling pointer is redirected to crafted zend_fcall_info and zend_internal_function structures. 4. Execution: PHP calls zend_call_function(), resulting in arbitrary system command execution.

Verification & Targets

---

Affected PHP Versions

The following table summarizes the PHP versions affected by CVE-2026-109618 and CVE-2026-109619, along with their support and patch statuses:

| PHP Branch | Status | Affected Versions | Fixed / Secure Version | Notes | | :--- | :--- | :--- | :--- | :--- | | PHP 8.5 | Supported (Active) | < 8.5.12 | 8.5.12 | Emergency security release published | | PHP 8.4 | Supported (Active) | < 8.4.27 | 8.4.27 | Emergency security release published | | PHP 8.3 | Supported (Active) | < 8.3.36 | 8.3.36 | Emergency security release published | | PHP 8.2 | Supported (Security Only) | < 8.2.35 | 8.2.35 | Emergency security release published | | PHP 8.1 | End of Life (EOL) | All 8.1.x versions | No Official Patch (EOL) | Set session.upload_progress.enabled = Off or use ELS/distro backports | | PHP 8.0 | End of Life (EOL) | All 8.0.x versions | No Official Patch (EOL) | Official support ended; configuration mitigation is mandatory | | PHP 7.x | End of Life (EOL) | All 7.0 - 7.4 versions | No Official Patch (EOL) | Core ext/session logic vulnerable; urgent mitigation or upgrade required | | PHP 5.x | End of Life (EOL) | 5.4.0+ (with RFC1867 progress tracking) | No Official Patch (EOL) | Official support ended; isolate host or disable upload progress |

[!WARNING]
PHP 8.1 and older End-of-Life (EOL) versions do not receive official security patches from the PHP Foundation. For these environments, immediately apply session.upload_progress.enabled = Off or rebuild PHP from source using the provided C source patch.

---

Threat Landscape & Detection Guidance

Exploitation of php2shell typically manifests as anomalous child processes spawned directly by PHP worker processes (php-fpm, php-cgi, php-cgi.exe, httpd, apache2).

Behavioral Indicators & Suspicious Child Processes

Monitor and alert on PHP worker processes executing:

Monitoring Recommendation

For Linux-based web environments without an endpoint detection agent, tools like Florian Roth's free process-watcher can be run in observe mode to flag unusual child process spawning in real time.

---

Action Items for Organizations

1. Inventory All PHP Environments:

2. Prepare for Patch Windows: 3. Isolate End-of-Life (EOL) Installations: 4. Incident Response & Investigation: ---

Proof of Concept (PoC)

A fully automated one-click remote exploit targeting CVE-2026-109618 is available in poc_109618.py. The exploit bypasses ASLR remotely using plain HTTP requests to achieve reliable arbitrary command execution.

Exploit Architecture & Stages

The attack chain consists of four sequential stages over HTTP:

1. Stage 0 — HTTP Worker Rotation: Aborts the current prefork worker over HTTP to ensure a clean heap state in the newly spawned worker child. 2. Stage 1 — Heap Base Leak: Induces an out-of-memory (OOM) condition via an oversized multipart field (--huge-mb, default 12MB) to trigger uninitialized memory leakage through Set-Cookie: PHPSESSID, extracting the Zend MM 2MB-aligned chunk base. 3. Stage 2 — Libphp Base Leak: Exploits session serialization / HashTable allocation alignment to leak the ZVAL_PTR_DTOR function pointer via Set-Cookie, computing the base address of libphp.so. 4. Stage 3 — Fake Reference & Arbitrary Execution: Forges a fake HashTable structure embedded inside a 167-byte zend_string with pDestructor pointed directly to zif_system in libphp.so. The crafted reference overwrites PS(http_session_vars). When PHP frees the session data, zif_system executes the supplied command.

[!NOTE]
The command is embedded directly inside a 167-byte live zend_string carrier (0x98 header + NUL byte limit), restricting inline command strings to maximum 14 bytes (MAX_CMD = 14). For longer commands, chain through a short trigger such as `sh/out/p1' --proof-file out/p1

Execute command writing to webroot and verify via HTTP GET fetch

python3 poc_109618.py -u http://127.0.0.1:8088/index.php -c 'id>p1.txt' --fetch /p1.txt

Command-Line Options
| Option | Description | Default | | :--- | :--- | :--- | | -u, --url | (Required) Target PHP endpoint URL | None | | -c, --cmd | Command to execute (maximum 14 bytes) | id>/out/p1 | | --proof-file | Path to local proof file to check post-exploitation; '' disables | out/p1 | | --fetch | Relative HTTP path to GET after exploitation (e.g. if writing to webroot) | "" | | --profile | Target build profile: bookworm (official php:8.4.26-apache) or lab (Apache 2.4.68) | bookworm | | --zif-offset | Offset of zif_system in libphp.so (hex format e.g. 0x43a870) | Loaded from offsets file | | --dtor-offset | Offset of ZVAL_PTR_DTOR in libphp.so (hex format e.g. 0x613c50) | Loaded from offsets file | | --htdata-offset | Chunk-relative offset of the 167-byte live string carrier | Profile dependent (0x690d8 or 0x6e0d8) | | --offsets-file | Path to load/store derived libphp offsets | out/offsets.env | | --docker-container| Docker container name to automatically derive offsets on localhost | php2shell-target | | --no-auto-offsets | Disable automatic offset extraction via Docker helper | False | | --huge-mb | Size in MB of the OOM payload; must exceed target memory_limit | 12 | | --timeout | Per-request network socket timeout in seconds | 30.0 | | --retries | Number of attempts per leak stage (stage 3 runs retries + 2) | 3 | | --no-pre-rotate | Skip the initial worker rotation (Stage 0) | False | | --no-retry-rotate | Do not rotate workers between failed stage attempts | False | | -q, --quiet | Suppress verbose output logging | False |

Profiles & Offsets

The exploit script supports profile-based presets:

  • --profile bookworm (Default): Calibrated for the official Docker library image php:8.4.26-apache running on Debian 12 (Bookworm) with Apache 2.4.69.
  • --profile lab: Calibrated for custom/minimal Apache 2.4.68 builds.
When targeting local Docker containers (127.0.0.1 / localhost), the script can automatically extract binary symbol offsets directly from the running container using docker/offsets.py and cache them in out/offsets.env. For remote targets where binary layout differs from Debian 12, provide --zif-offset and --dtor-offset manually.

---

Mitigation & Source Patching

Until official vendor packages are updated in your repositories, you can protect your environments using configuration changes, automated scripts, or by compiling PHP with the included source patch.

1. Configuration Mitigation (Immediate Stopgap)

The vulnerability relies on PHP's session upload progress mechanism (session.upload_progress.enabled), which is enabled by default. Disabling this directive neutralizes the attack vector while preserving regular file upload functionality:

In your php.ini:

ini session.upload_progress.enabled = Off

Or for PHP-FPM pool configurations (e.g., /etc/php/*/fpm/pool.d/www.conf):
ini php_admin_flag[session.upload_progress.enabled] = off

After modifying the configuration, reload/restart your web services (e.g. systemctl reload php-fpm or systemctl reload apache2).

2. Automated Quick-Fix Script

A mitigation helper script is available under the quick-fix/ directory:
  • Check Current Status:
bash sudo ./quick-fix/run.sh --check
- Apply Mitigation (Dry Run):
  
bash sudo ./quick-fix/run.sh --dry-run
- Apply Mitigation:
  
bash sudo ./quick-fix/run.sh
- Revert Changes:
  
bash sudo ./quick-fix/run.sh --revert

3. Source Code Patch (session-upload-progress-counters.patch)

If you build PHP from source or maintain custom distribution packages, a C-level source patch is provided under patch/session-upload-progress-counters.patch.

What the patch fixes: The patch resolves the root cause in ext/session/session.c and ext/session/php_session.h. Instead of maintaining vulnerable, raw zval * bucket pointers (post_bytes_processed and current_file_bytes_processed) into dynamic HashTable structures (which become dangling pointers when the hash table is cleared or re-allocated during upload progress updates), the patch:

  • Stores counters as direct zend_long primitives.
  • Introduces php_session_rfc1867_sync_counters() to safely resolve and update array entries without dangling references.
How to Apply the Patch:

1. Navigate to the root of your php-src source directory:

bash cd /path/to/php-src

2. Test applying the patch (dry-run):
   
bash # Using git (if building from a git clone) git apply --check /path/to/patch/session-upload-progress-counters.patch

# OR using GNU patch patch -p1 --dry-run < /path/to/patch/session-upload-progress-counters.patch


3. Apply the patch:
   
bash # Using git git apply /path/to/patch/session-upload-progress-counters.patch

# OR using GNU patch patch -p1 < /path/to/patch/session-upload-progress-counters.patch


4. Recompile and install PHP:
   
bash ./buildconf --force # if needed ./configure make -j"$(nproc)" sudo make install

5. Restart your PHP runtime / web services:
   
bash sudo systemctl restart php-fpm # or sudo systemctl restart apache2

Community Backports for EOL Versions (PHP 5.6, 7.4, 8.0, 8.1)

For legacy systems that cannot immediately upgrade to supported PHP 8.2+ releases (e.g. legacy OpenCart, WordPress, or control panels running on PHP 5.6, 7.4, 8.0, or 8.1), dedicated backports combining the official PHP Group OOM fix with the root-cause counter sync are available:

  • 👉 Repository: Anton-Barinov/php2shell-patches
  • Includes automated build scripts to compile isolated, side-by-side runtimes into /opt/php--patched without overwriting system packages, plus multi-PHP FPM pool hardening tools.

4. Cloudflare WAF Custom Rules

Recommended Cloudflare WAF rule templates to filter malicious traffic are located in the cloudflare-rule-fix/ directory:
  • Comprehensive multipart blocking (excluding legitimate upload routes)
  • Enterprise plan PHP_SESSION_UPLOAD_PROGRESS request body inspection
  • Note: Blocking requests based solely on the PHPSESSID cookie is strongly discouraged as it breaks valid user sessions. Refer to cloudflare-rule-fix/README.md for full rule syntax and details.

5. FrankenPHP Caddyfile Configuration

To disable the session upload progress mechanism globally in FrankenPHP environments, a Caddyfile snippet is provided.

Add the contents of frankenphp/Caddyfile-snippet to your global Caddyfile block:

caddyfile { frankenphp { php_ini session.upload_progress.enabled 0 } }

6. Lighttpd Configuration

For environments running Lighttpd, you can block multipart requests (POST, PUT, PATCH) on virtual hosts or directories that do not accept file uploads using lighttpd/php2shell.conf:

lighttpd $HTTP["request-method"] =~ "^(POST|PUT|PATCH)$" { $REQUEST_HEADER["Content-Type"] =~ "(?i)^\s*multipart/form-data([;,[:space:]]|$)" { url.access-deny = ( "" ) } }

7. Apache Mitigation (ModSecurity & .htaccess)

Two mitigation options are provided for Apache environments:
apache SecRequestBodyAccess On SecRule ARGS_NAMES "@streq PHP_SESSION_UPLOAD_PROGRESS" \ "id:1026109618,phase:2,t:none,deny,status:403,log,\ msg:'php2shell: PHP_SESSION_UPLOAD_PROGRESS field blocked (CVE-2026-109618/109619)'"

  • .htaccess / mod_rewrite Rule: For directories that do not require file uploads, block multipart requests before they reach the PHP interpreter using apache/.htaccess:
apache RewriteEngine On RewriteCond %{REQUEST_METHOD} ^(POST|PUT|PATCH)$ [NC] RewriteCond %{HTTP:Content-Type} ^[[:space:]]*multipart/form-data([;,[:space:]]|$) [NC] RewriteRule ^ - [F,L] ```

---

Disclaimer

This project is intended strictly for educational purposes and authorized security research. Use only in environments you own or have explicit permission to test.

---

Author & Contact

GitHub Stars & Activity

1,043Stars
262Forks
0Open issues
ShellLanguage

GitHub Popularity

GitHub stars1,043
Forks262
Open issues0
Primary languageShell
License-
Stars gained today0
Created-
Last pushed-

Trending History

Weekly boardrank #26 · ▲ 0 stars

Related GitHub Projects

1

anhao / ai-pose-gallery-zh

HTML★ 2,551⑂ 668
→
2

andyhuo520 / digital-human-koubo

TypeScript★ 1,400⑂ 323
→
3

Motionsites-AI / claude-skill

Python★ 1,021⑂ 106
→
4

kargulstudio / calender-app-design

TypeScript★ 795⑂ 96
→
5

smithjohn78390 / tongjiang-lab

HTML★ 760⑂ 206
→
6

yaojingang / GEOInflow

TypeScript★ 707⑂ 227
→
7

blakeandersonw / ai-app-playbook

TypeScript★ 571⑂ 77
→
8

deepopen-com / deepopen-3d-webs

Python★ 517⑂ 1
→

More Trending Repositories