The project's README from github.com/eness/php2shell-CVE-2026-109618-CVE-2026-109619-PoC. As one markdown file: README.md.
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.
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()).
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:
POST request activates progress tracking with default configuration values (session.upload_progress.enabled = 1).zend_hash_update() destroys the previous data tree using the destructor zval_ptr_dtor, freeing the memory block.zend_fcall_info and zend_internal_function structures.zend_call_function(), resulting in arbitrary system command execution.php-src builds (including versions 8.4.4 and 8.2.34).--syms) between zval_ptr_dtor and zend_call_function to adapt to distribution-specific binary layouts (e.g., Debian Bookworm, Ubuntu Noble, Ubuntu Jammy).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 = Offor rebuild PHP from source using the provided C source patch.
Exploitation of php2shell typically manifests as anomalous child processes spawned directly by PHP worker processes (php-fpm, php-cgi, php-cgi.exe, httpd, apache2).
Monitor and alert on PHP worker processes executing:
/bin/sh, /bin/bash, cmd.exe, powershell.exepython, perlcurl, wget, nc, certutil.exe/dev/tcp/, fsockopen, mkfifowhoami, id, uname -a, ipconfigFor 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.
php.exe, php-cgi.exe)./tmp, /var/tmp) for dropped webshells or transient execution artifacts.This repository is dedicated to security research and Proof-of-Concept (PoC) development for php2shell (CVE-2026-109618 / CVE-2026-109619).
The PoC exploit is currently being developed and tested. The code will be published in this repository very soon.
⭐ Star this repository to stay updated on the upcoming PoC release.
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.
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:
session.upload_progress.enabled = Off
Or for PHP-FPM pool configurations (e.g., /etc/php/*/fpm/pool.d/www.conf):
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).
A mitigation helper script is available under the quick-fix/ directory:
sudo ./quick-fix/run.sh --check
sudo ./quick-fix/run.sh --dry-run
sudo ./quick-fix/run.sh
sudo ./quick-fix/run.sh --revert
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:
zend_long primitives.php_session_rfc1867_sync_counters() to safely resolve and update array entries without dangling references.How to Apply the Patch:
Navigate to the root of your php-src source directory:
cd /path/to/php-src
Test applying the patch (dry-run):
# 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
Apply the patch:
# 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
Recompile and install PHP:
./buildconf --force # if needed
./configure <your-options>
make -j"$(nproc)"
sudo make install
Restart your PHP runtime / web services:
sudo systemctl restart php-fpm
# or
sudo systemctl restart apache2
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:
/opt/php-<ver>-patched without overwriting system packages, plus multi-PHP FPM pool hardening tools.Recommended Cloudflare WAF rule templates to filter malicious traffic are located in the cloudflare-rule-fix/ directory:
PHP_SESSION_UPLOAD_PROGRESS request body inspectionPHPSESSID cookie is strongly discouraged as it breaks valid user sessions. Refer to cloudflare-rule-fix/README.md for full rule syntax and details.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:
{
frankenphp {
php_ini session.upload_progress.enabled 0
}
}
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:
$HTTP["request-method"] =~ "^(POST|PUT|PATCH)$" {
$REQUEST_HEADER["Content-Type"] =~ "(?i)^\s*multipart/form-data([;,[:space:]]|$)" {
url.access-deny = ( "" )
}
}
Two mitigation options are provided for Apache environments:
ModSecurity Rule: Block requests containing the PHP_SESSION_UPLOAD_PROGRESS parameter using apache/modsecurity-php2shell.conf:
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:
RewriteEngine On
RewriteCond %{REQUEST_METHOD} ^(POST|PUT|PATCH)$ [NC]
RewriteCond %{HTTP:Content-Type} ^[[:space:]]*multipart/form-data([;,[:space:]]|$) [NC]
RewriteRule ^ - [F,L]
This project is intended strictly for educational purposes and authorized security research. Use only in environments you own or have explicit permission to test.