Back Sploitus Exploit for Improperly Controlled Sequential Memory Allocation in Php
> Shell scripts that check Linux hosts for known vulnerabilities, report whether each one is vulnerable, mitigated or fine, and can apply the fix on request. Designed to run locally or across fleets via SSH, Ansible or pssh.
| Check | Vulnerability | Severity | `--fix` does |
| `CVE-2026-109618` | PHP: remote code execution via OOM corruption (CVE-2026-109618) and via stale global state (CVE-2026-109619) | Critical, CVSS 9.2, remote and unauthenticated | Upgrades the PHP packages, restarts PHP-FPM and Apache (mod_php) |
| `CVE-2026-31431` | Copy Fail: Linux kernel `algif_aead` local privilege escalation | High, CVSS 7.8, local | Installs the kernel update (reboot by hand), blacklists and unloads `algif_aead` |
List them with `./cve-check.sh --list`. A check is selected by its name or by any CVE it covers, so `./cve-check.sh CVE-2026-109619` runs the PHP check.
curl -fsSL | sudo bash -s -- --fix
When it is piped like this, `cve-check.sh` downloads the rest of the project (the checks in `checks/` and `lib/`) from GitHub into a temporary directory, runs from there and removes it afterwards. `--fix` asks its questions on the terminal (`/dev/tty`), so it also works piped in an interactive session.
> **Tip:** Pin a commit SHA in production so the script cannot change under you. `CVE_CHECK_REF` makes the download of the checks use the same commit:
> curl -fsSL | sudo CVE_CHECK_REF=COMMIT_SHA bash
## Download and inspect first (recommended)
git clone
./cve-check.sh # without root
sudo ./cve-check.sh # full results
sudo ./cve-check.sh --fix # check, then fix what can be fixed
--fix After a check finds a problem, apply its remediation
(package update, service restart, mitigation). Asks before
each change and checks again afterwards. Needs root.
-y, --yes Answer yes to every --fix question (for unattended runs).
| `1` | At least one check found the host vulnerable |
| `2` | Only mitigated findings: a workaround is active, the official fix is still missing |
| `3` | Usage error, or the checks could not be downloaded |
ssh "$HOST" "curl -fsSL | sudo bash -s -- --no-color"
ansible.builtin.command: /opt/cve-check/cve-check.sh --no-color
"curl -fsSL | sudo bash -s -- --no-color"
For unattended fixing, add `--fix --yes`. It never reboots: after a kernel update the summary still shows the running kernel as vulnerable until the host is rebooted.
============================================================
============================================================
============================================================
PHP: remote code execution via OOM corruption and stale global state
============================================================
[SAFE] /usr/bin/php7.4: PHP 7.4.33 with the fixes backported (both CVEs are in the package changelog).
[WARN] /usr/sbin/php-fpm8.3: PHP 8.3.35 is vulnerable, fixed in 8.3.36. The package changelog has no backport of CVE-2026-109618 CVE-2026-109619.
[INFO] Running: php-fpm: master process (/etc/php/8.3/fpm/php-fpm.conf)
[WARN] Container shop (shop-app:latest): PHP 8.4.26 is vulnerable, fixed in 8.4.27.
>>> Workarounds (partial, only the update fixes it)
[NOTE] /usr/sbin/php-fpm8.3: session.upload_progress.enabled is enabled (0 of 1 pools disable it), set php_admin_value[session.upload_progress.enabled] = 0.
============================================================
============================================================
VULNERABLE CVE-2026-109618 CVE-2026-109619 PHP: remote code execution via OOM corruption and stale global state
OK CVE-2026-31431 Copy Fail: Linux kernel algif_aead local privilege escalation
============================================================
## PHP: CVE-2026-109618 and CVE-2026-109619
Two use-after-free bugs in PHP, published on 21 October 2026. An unauthenticated remote attacker can run code with the privileges of the PHP worker.
- **CVE-2026-109618, RCE via OOM corruption:** PHP leaves an out-of-memory error with `longjmp()`. When that happens while a request is still being set up, request cleanup works on half-initialized memory. Crafted multipart requests trigger it, on mod_php before any application code runs.
- **CVE-2026-109619, RCE via stale global state:** a fatal error or OOM in one request leaves global state pointing at freed memory, and a later request on the same worker uses it. Session upload progress (on by default) and PHP 8.5 `fatal_error_backtraces` are the confirmed paths.
| **CVE** | CVE-2026-109618, CVE-2026-109619 |
| **Fixed in** | 8.2.35, 8.3.36, 8.4.27, 8.5.12 |
| **PHP 8.1 and older** | No upstream release; vendor backports exist (deb.sury.org, Remi, LTS vendors) |
| **Remotely exploitable** | Yes, unauthenticated |
| Every PHP build (CLI, PHP-FPM, php-cgi, lsphp, FrankenPHP) in the distro, Remi, cPanel, Plesk, CloudLinux, DirectAdmin and LiteSpeed locations, by version, or by the package changelog for distro backports | No |
| Apache mod_php modules (`libphp*.so`) and whether mod_php is enabled | No |
| Running PHP servers: FPM masters, `php -S` built-in servers, php-cgi, lsphp, FrankenPHP | No |
| Workers still running the code from before the last update (deleted binary or `libphp` still mapped) | **Yes** |
| Running Docker containers from official PHP images (`PHP_VERSION`), without entering them | Root or the `docker` group |
| Workarounds for vulnerable builds: `session.upload_progress.enabled` per FPM pool, `fatal_error_backtraces` on 8.5, mod_php `php.ini` (Debian layout) | No |
Limits: PHP installed inside a container without an official PHP image is not detected. The advisories do not name the built-in server (`php -S`), but it parses uploads the same way and keeps one process across requests, so treat it as affected.
# Debian / Ubuntu (add 'libapache2-mod-php*' when mod_php is installed)
sudo apt update && sudo apt install --only-upgrade 'php*'
# Then restart every PHP server so no worker keeps the old code
sudo systemctl restart php8.3-fpm apache2
# Containers: rebuild on the patched base image, or pull the new image
docker compose build --pull && docker compose up -d
Until the update is in, these reduce the risk without removing it: `php_admin_value[session.upload_progress.enabled] = 0` in every FPM pool (also recommended after the update when nothing uses upload progress), `fatal_error_backtraces = 0` on PHP 8.5, restart the workers, and block multipart requests where the application takes no uploads.
**Copy Fail** is a high-severity local privilege escalation in the Linux kernel's `algif_aead` cryptographic module. A logic flaw introduced in 2017 allows any unprivileged local user to write 4 controlled bytes into the page cache of any readable file, enough to overwrite a setuid binary and obtain root. A working proof of concept is public.
| **Affected** | Linux kernels 4.13 to 6.x (2017 to 2026) |
| **Fixed in** | 7.0, 6.19.12, 6.18.22, and distribution kernels that list the CVE in their changelog |
| **Remotely exploitable** | No, local access required |
| Kernel version: affected range, or an upstream release with the fix | No |
| Distribution patch status: CVE listed in the running kernel's changelog (dpkg, rpm, pacman) | No |
| `algif_aead` module: loaded, present on disk, or blacklisted | No |
| Boot parameter `initcall_blacklist=algif_aead_init` | No |
| AF_ALG socket reachability (needs `python3`) | No |
| SELinux / AppArmor status (informative, they only help if the policy denies AF_ALG) | AppArmor: **Yes** |
Once the running kernel is confirmed patched, the module findings are only reported for information.
**2. Blacklist the module** *(immediate, persistent)*
sudo tee /etc/modprobe.d/copyfail.conf << 'EOF'
**3. Unload the module now** *(immediate, not persistent across reboots)*
**4. Kernel boot parameter** *(alternative to the blacklist)*
Add `initcall_blacklist=algif_aead_init` to your GRUB config and reboot.
- `bash` 4.4 or newer, with coreutils, `awk`, `grep` and `ps`. The scripts do not run under `sh`, `ash` or `dash`; on Alpine install bash first with `apk add bash`.
- `curl` and `tar` for the piped `curl | bash` mode.
- `python3` for the AF_ALG test (skipped without it).
- `--fix` supports apt (Debian, Ubuntu), dnf/yum (RHEL, Fedora, Amazon Linux) and zypper (SUSE), and restarts services with systemd. Elsewhere it says what to do by hand.
Each check is one file in `checks/`, named after its main CVE. `cve-check.sh` sources it in a subshell, so checks cannot see each other. A check defines:
| `CHECK_TITLE` | yes | One-line description |
| `CHECK_CVES` | yes | Array of the CVEs it covers, also usable to select it |
| `CHECK_REFS` | yes | Array of reference URLs |
| `check_run` | yes | Runs the checks and reports with the helpers below |
| `check_advice` | no | Prints the manual remediation when the host is not OK |
| `check_fix` | no | Applies the remediation (runs as root, after `check_run`, so it can use the state `check_run` left) |
- Output: `section`, `pass`, `warn` (marks the host vulnerable), `mitig` (marks a mitigation as active), `info`, `note`, `fixed`, `failed`.
- `confirm "question"` asks on the terminal, or answers yes with `--yes`; every change in `check_fix` should go through it.
- `version_lt`, `pkg_manager`, `pkg_owner`, `pkg_changelog`, `pkg_upstream_version`, `running_units`, `has_cmd`.
The verdict follows the helpers: no `warn` means OK, `warn` with at least one `mitig` means MITIGATED, `warn` alone means VULNERABLE.
MIT: use freely, no warranty implied. Always review scripts before running them as root.
The full story
This article is one source in a clustered incident — the cluster page carries the summary, timeline and every other outlet covering it.
