Skip to content

About

Check, apply and test AWS WAF mitigations for PHP2Shell (CVE-2026-109618 / CVE-2026-109619)

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

php2shell-guard logo

php2shell-guard

Check, apply and test AWS WAF mitigations for PHP2Shell (CVE-2026-109618 and CVE-2026-109619),
the unauthenticated PHP RCE bugs fixed in PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35.

An exploit request stopped by AWS WAF before it reaches the PHP origin, while normal traffic goes through


Upgrading PHP is the real fix. This tool is for the days between the advisory and the last server getting patched: it tells you which web ACLs are covered, adds the rules AWS recommends without dropping anything you already have, and lets you prove the block from outside. There's also a host script that checks PHP versions and the php.ini settings that reduce exposure.

Write-up with screenshots: Stopping PHP2Shell with AWS WAF. The Cloudflare side is covered in Cloudflare already blocks PHP2Shell. Is it protecting you?

What it does

Command
check Lists every web ACL (CloudFront and regional) and says whether the PHP2Shell rule is there, whether it blocks or only counts, and whether an Allow rule runs before it and lets requests skip it. Exit code 0 only if every web ACL is OK.
apply Adds the rules from the AWS guidance at the top of each web ACL and moves the existing rules down by 10, keeping their order. Dry run by default. Backs up each web ACL to backups/ before changing it.
restore Puts a web ACL back from one of those backups.
test Sends a harmless POST carrying the field the rule looks for and expects a 403.
host/check-php-host.sh Runs on a PHP server: version check, session.upload_progress, fatal_error_backtraces, FPM pm.max_requests, optional scan for recently changed .php files, optional --fix.

The rules (in rules/php2shell-rules.json):

Rule Default Matches
PHP2Shell Block POST + PHPSESSID (cookie or body) + PHP_SESSION_UPLOAD_PROGRESS in the body
Block-Multipart-FormData Count any multipart/form-data request (would block uploads)
Block-Oversize-Body Count bodies over 8 KB
RateLimit-Posts Count more than 100 POSTs per IP per minute

Usage

Needs Python 3.9+ and boto3. AWS CloudShell has both, so the quickest way is to clone it there.

git clone https://github.com/jaba0x/php2shell-guard && cd php2shell-guard
pip install -r requirements.txt   # not needed in CloudShell

# What's protected right now?
./php2shell_guard.py check
./php2shell_guard.py check --scope regional --regions eu-central-1 us-east-1

# See the plan, then apply it
./php2shell_guard.py apply --acl my-web-acl
./php2shell_guard.py apply --acl my-web-acl --apply

# Only the main rule, in Count mode first
./php2shell_guard.py apply --core-only --core-count --apply

# Verify from outside
./php2shell_guard.py test https://www.example.com/

# Undo
./php2shell_guard.py restore backups/my-web-acl-20261022-150000.json --apply

CloudFront web ACLs always live in us-east-1. Regional ones (ALB, API Gateway, AppSync) are scanned in the regions you pass with --regions.

IAM permissions: wafv2:ListWebACLs, wafv2:GetWebACL and wafv2:CheckCapacity for check and dry runs, plus wafv2:UpdateWebACL for --apply and restore.

On the PHP servers

curl -fsSLO https://raw.githubusercontent.com/jaba0x/php2shell-guard/main/host/check-php-host.sh
bash check-php-host.sh                                   # report
bash check-php-host.sh --scan /var/www                   # plus .php files changed in the last 14 days
sudo bash check-php-host.sh --fix                        # write conf.d/99-php2shell.ini, then restart PHP

Read the script before you run it with sudo. Distro packages (Ubuntu, Debian, RHEL) sometimes ship the fix as a backport under an older version number, so a "VULNERABLE" result there means "check your vendor's advisory".

Things to know

  • update_web_acl replaces the whole web ACL. The tool copies back the default action, custom response bodies, CAPTCHA and challenge settings, token domains and the body inspection config from what it read, and uses the lock token so it fails instead of overwriting someone else's change.
  • The new rules go above your Allow rules on purpose. If an allowlist rule runs first, matching requests never reach the PHP2Shell rule.
  • Leave the three optional rules in Count until you've looked at their CloudWatch metrics for a day or two.
  • A WAF can't see inside PHP's memory. CVE-2026-109619 is mostly out of its reach. Set session.upload_progress.enabled = 0, set fatal_error_backtraces = 0 on 8.5, and upgrade.

Tests

pip install -r requirements-dev.txt
pytest -q

The tests run against a mocked AWS (moto), so they don't touch a real account.

License

MIT

About

Check, apply and test AWS WAF mitigations for PHP2Shell (CVE-2026-109618 / CVE-2026-109619)

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages