PHP2Shell Vulnerability: Step-by-Step Security Guide for Ubuntu and Apache Servers
Data verification date: October 22, 2026
When you see a security alert about PHP2Shell, the first thing to do is determine which PHP version is actually running on your server. Then, check if a fix is available in your package source, install the patched package, and restart the services that keep PHP code in memory.
This guide is designed for Ubuntu servers running PHP and Apache installed with APT. The update method may differ for systems using Docker, hosting panels, PHP compiled from source code, or other Linux distributions. Before starting the process, ensure you have a usable backup and consider the possibility of a short service interruption.
What is PHP2Shell?
PHP2Shell is the name given to two critical security vulnerabilities discovered in the PHP core. Under the right conditions, these vulnerabilities could allow remote code execution without authentication. The PHP project released the relevant fixes on October 21, 2026.
Security vulnerability The core issue is CVE-2026-109618 Incomplete internal data being accepted as valid during memory shortage CVE-2026-109619 Subsequent requests being able to revert to the previous state after memory is freed
A successful attack typically results in code execution with the web worker's privileges. While this doesn't directly mean root access, it poses a significant risk to database passwords, API keys, .env files, user data, and other secrets that the application has access to.
Which systems are affected?
All PHP installations that process web requests should be carefully evaluated. The risk is particularly high if mod_php is used on Apache; one of the verified attack pathways can be triggered before the application code even starts running. Using PHP-FPM also does not eliminate the need for updates.
Therefore, using Laravel, Symfony, WordPress, or another PHP framework does not change your security responsibility. Laravel maintenance mode or protection added from within the application may not prevent an attack path that can be triggered before the PHP runtime layer. If a patch cannot be applied immediately, consider restricting external access to PHP or temporarily shutting down the service.
Which PHP version should you switch to?
The table below lists the first official PHP releases that addressed the vulnerabilities. Always choose a newer security release if one is available for your current branch.
PHP branch First patched official releases PHP 8.2 8.2.35 PHP 8.3 8.3.36 PHP 8.4 8.4.27 PHP 8.5 8.5.12
However, distributions like Ubuntu may roll back security fixes to the current package version. Therefore, don't conclude that a package is insecure just by looking at the short version number in the php -v output. For example, a version number that appears older in Ubuntu's official packages might contain the relevant CVE fixes. It's necessary to check the full package version and package source.
1. Identify the installed PHP packages.
First, check the PHP version running in the command line:
php -v
This command only shows the PHP version in the CLI environment. It alone does not prove that Apache is using the same version. To inventory the installed packages, run the following command:
dpkg-query -W \ -f='${db:Status-Status}\t${binary:Package}\t${Version}\n' \ 'php*' 'libapache2-mod-php*' | awk '$1 == "installed"'
This output allows you to see all installed PHP branches, extensions, FPM packages, and Apache modules together. Note that there may be multiple PHP versions on the server.
2. Check which PHP implementation Apache uses.
To see the Apache modules installed:
sudo apache2ctl -M
If php_module is found in the output, Apache may be using mod_php . To find out the version branch:
grep -RnE 'LoadModule.*php' /etc/apache2/mods-enabled
For example, seeing the result libphp8.4.so indicates that Apache has installed the PHP 8.4 module. However, you also need to check which package revision it belongs to.
To check PHP-FPM services and whether Apache is pointing to FPM sockets:
systemctl list-units --type=service --all 'php*-fpm.service' grep -RnE 'SetHandler|ProxyPassMatch|php.*fpm' \ /etc/apache2/sites-enabled /etc/apache2/conf-enabled
It's possible for different sites to use different PHP-FPM versions. Therefore, evaluate all active site configurations on the server, not just the default domain.
3. Check the current package in the repository.
First, update the APT package index:
sudo apt update
Next, check for installed and candidate versions of packages like PHP 8.4:
apt-cache policy \ php8.4-cli php8.4-common php8.4-fpm libapache2-mod-php8.4 apt-mark showhold
Installed ' field shows the installed version, while Candidate field shows the version that can be installed according to your APT configuration. A patched Candidate version doesn't necessarily mean the update has been applied yet. Also, apt update only refreshes package information; it doesn't upgrade packages.
4. Update installed PHP packages.
First, list which PHP 8.2 and PHP 8.4 packages are installed:
mapfile -t php_packages < <( dpkg-query -W -f='${db:Status-Status} ${binary:Package}\n' \ 'php8.2*' 'php8.4*' \ 'libapache2-mod-php8.2' 'libapache2-mod-php8.4' | awk '$1 == "installed" {print $2}' ) printf '%s\n' "${php_packages[@]}"
After carefully checking the list, run the simulation first:
sudo apt-get --simulate --no-remove install --only-upgrade "${php_packages[@]}"
If there are no unexpected package removals or dependency issues, initiate the update:
sudo apt-get --no-remove install --only-upgrade "${php_packages[@]}"
Updating only php8.4-cli package is not enough. The Apache module, PHP-FPM, common PHP packages, and the extensions used must also be up-to-date. If a question arises regarding locally modified configuration files, do not overwrite the default files without examining the differences.
5. Restart the Apache and PHP-FPM services.
Once the package update is complete, older processes may continue executing previous PHP code in their memory. Therefore, the service restart step is critical.
sudo apache2ctl configtest sudo systemctl restart apache2
If the configuration test returns a Syntax OK result, Apache can be restarted. If you are using PHP 8.4 FPM, also refresh the relevant service:
sudo systemctl try-restart php8.4-fpm
If you are using a different PHP branch, change the service name accordingly. Also, restart any long-running PHP processes running from Laravel Horizon, queue worker, Octane, Supervisor, or systemd, according to how your application works.
6. Verify the update.
After the update, check the status of both packages and services:
php -v dpkg-query -W \ -f='${db:Status-Status}\t${binary:Package}\t${Version}\n' \ php8.4-cli php8.4-common php8.4-fpm libapache2-mod-php8.4 systemctl is-active apache2 systemctl --failed
Verification should consist of three steps: ensuring the correct package version is installed, pointing the site to the correct PHP environment, and restarting the relevant services. Do not leave a publicly accessible phpinfo() page. If necessary, use a temporary diagnostic method accessible only to administrators and remove it once the process is complete.
Examine the signs of the breach after patching.
The patch closes the vulnerability; however, it does not undo a potential attack that has already occurred. Examining Apache and application logs is a good starting point.
sudo journalctl -u apache2 --since "24 hours ago" --no-pager -n 200 sudo tail -n 200 /var/log/apache2/error.log
Unexpected crashes, memory errors, modified PHP files, new cron tasks, unfamiliar SSH keys, and unusual external connections should be investigated. The absence of errors in the logs does not guarantee the system is secure. If a breach is suspected, isolate the system, preserve logs and disk evidence if possible, and then renew any passwords and API keys that may have been accessed.
Conclusion
Kernel-level vulnerabilities like PHP2Shell require a broader intervention than simply updating application dependencies. Updating Composer packages alone is insufficient; PHP packages that handle web requests, Apache modules, FPM services, and long-running worker processes must all be addressed together.
To respond more quickly to future security announcements, keep a record of each site's PHP version, package source, Apache or FPM usage, responsible services, and last update date.
Sources
Keywords: Ferhat Gölge, homepage, portfolio, blog, Laravel, software developer
Frequently Asked Questions
What is the PHP2Shell vulnerability?
PHP2Shell is the name given to the CVE-2026-109618 and CVE-2026-109619 vulnerabilities in the PHP core. These vulnerabilities, under certain conditions, could allow attackers to remotely execute code with the privileges of a web service without authenticating.
If I'm using Laravel or WordPress, will PHP2Shell affect me?
Yes. Since the problem lies in the PHP runtime environment, using Laravel, WordPress, or Symfony alone will not provide protection. Apache mod_php installations carry a particularly high risk; systems using PHP-FPM also need to be updated.
Which PHP version should I use to patch the PHP2Shell vulnerability?
The first official patched versions are PHP 8.2.35, 8.3.36, 8.4.27, and 8.5.12 . You should upgrade to this version or newer for the branch you are using. Compare the full package version with your provider's security announcement, as Linux distributions may roll back the fix to older versions.
Would a Composer update or Laravel maintenance mode be sufficient?
No. Composer updates application dependencies; it doesn't update the PHP core on the server. Laravel maintenance mode also doesn't prevent attack paths that can be triggered before the application code. You should update the PHP packages and restart the relevant Apache/PHP-FPM processes.
After updating PHP, do I need to perform any further checks?
Yes. Verify that the sites are indeed using the patched PHP environment, that the relevant services have been restarted, and that core processes are running. Also, review logs and unauthorized file changes from before the patch. The update does not clean up a previously occurred breach or a previously left-behind backdoor.