PHP2Shell is the name given to two PHP vulnerabilities, fixed on 21 October 2026, that let an attacker execute code on a web server with a single unauthenticated request. The UK's National Cyber Security Centre has told organisations running any version of PHP to update at once or, where they cannot, to take the affected systems offline.
A business on a supported PHP 8 release can close the hole with a patch. A business on PHP 7.4, 8.0 or 8.1, or on an application nobody can safely change, cannot, because those versions are end of life and received only a stop-gap source backport. For those businesses the question is no longer whether to leave legacy PHP but which stack to move to, and Python with Django is one of the two answers we give.
This post reports the facts, sets out the 48-hour response, lists what businesses stuck on old PHP tell us, explains when Python is the right destination and how the migration runs, covers the hardening that goes with it, and shows how our legacy code migration team delivers it. A companion post covers the Node.js migration path for PHP2Shell.
PHP2Shell: the facts as of 26 October
The two flaws are tracked as CVE-2026-109618 and CVE-2026-109619, each scored 9.2 on CVSS 4.0, and each allowing unauthenticated remote code execution. PHP published fixes and advisories for CVE-2026-109618 and CVE-2026-109619 on 21 October.
In the first, an out-of-memory condition interrupts PHP part-way through setting up a request, and the cleanup that follows treats half-built data as valid. In the second, state belonging to one request outlives its memory, so a later request on the same worker can pick it up.
Any PHP installation that answers web requests is in scope: PHP-FPM, php-cgi and Apache with mod_php, the last of which Snyk's analysis identifies as the most exposed. Sansec's research dates the affected code back to PHP 5.4. A working exploit has been demonstrated; at the time of writing, confirmed attacks in the wild have not been reported.
Fixed releases are PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35, with Linux distributions shipping patched builds under older version numbers. PHP 7.4, 8.0 and 8.1 are end of life and got a minimal source backport for people who compile PHP themselves, nothing more, and nothing for whatever comes next.
The NCSC's notice asks organisations to find every PHP installation, internet-facing first; update; apply the PHP Foundation's temporary mitigations where an update must wait; take systems offline where neither is quick; check exposed systems for compromise; and track vendors whose products bundle PHP. PHP itself says there are no complete mitigations and that updating is the only safe choice.
The 48-hour response
These six steps follow the NCSC's order and apply to any business with PHP reachable from the internet.
1. Inventory your PHP footprint. Record every server, container, hosted service and appliance running PHP, beginning with anything reachable from the internet, and include third-party products that ship with PHP inside them.
2. Move to a patched release. Install PHP 8.5.12, 8.4.27, 8.3.36 or 8.2.35, or your distribution's patched package, which may carry an older version string, then restart all PHP workers so the fix takes effect.
3. Use the interim mitigations only as a bridge. Where the update has to wait, apply the PHP Foundation's temporary measures, such as a low post_max_size and disabled session upload progress, and restart the workers, knowing PHP describes them as incomplete.
4. Disconnect what you cannot fix in time. The NCSC's position is that a system which cannot be updated or mitigated promptly should be taken offline rather than left exposed to unauthenticated code execution.
5. Look for signs of intrusion. Examine any internet-facing PHP system that stayed exposed after 21 October 2026 for backdoors and unexpected changes, and bring in an incident response provider if you find any.
6. Choose a future for end-of-life PHP. Sites on PHP 7.4, 8.0 or 8.1 have a one-off source backport and nothing further. Plan an upgrade to a supported PHP 8 release or a migration to Python with Django.
What businesses stuck on old PHP tell us
The sixth step is where this becomes a migration story. These are the six things we hear from businesses whose PHP cannot simply be updated, and what each one means.
“The agency that built it closed years ago.”
The code has had no owner since, and the business has been running it unchanged because changing it felt riskier than leaving it.
What it tells us: the application needs a new owner and a stack that owner can hire for. Python is one of the most widely taught languages, which makes that hiring easier.
“Half of what the site does is reporting and data crunching, and it's all in PHP.”
Nightly jobs, exports, reconciliations and dashboards bolted onto a web framework that was never meant for them.
What it tells us: the workload has outgrown the language it started in. Python's data and automation libraries are the reason many of these migrations choose it over a like-for-like PHP upgrade.
“We want to add AI features, and the PHP side is the blocker.”
Document classification, recommendations, forecasting: the models exist, but the application cannot talk to them cleanly.
What it tells us: the machine learning ecosystem lives in Python. Moving the application there removes a translation layer rather than adding one.
“Every security advisory is a panic because we can't tell what's safe to touch.”
No tests, no documentation, and a fear that a one-line change will break checkout.
What it tells us: migration is also the moment to put tests around the business rules, so the next advisory is a routine deploy. Django's conventions make that discipline easier to keep.
“We've been told PHP 8 won't run our code without a rewrite anyway.”
Removed functions, a dead framework and extensions that no longer exist mean the upgrade is a rebuild in all but name.
What it tells us: if a rewrite is unavoidable, the choice of language is open. That is when Python deserves a fair comparison against modern PHP.
“It's on a server nobody has logged into since the last developer left.”
Old operating system, old Apache, mod_php, and no idea what else is installed.
What it tells us: the hosting is as unmaintained as the code. A migration should land on a managed platform or containers with automatic security updates, whatever the language.
Patch, upgrade PHP, or migrate to Python?
Patch if you are on PHP 8.2 or newer and your application runs on the fixed release. If you are on an end-of-life version, or the code fails on modern PHP, or nobody can maintain it, you are migrating, and there are two sensible destinations.
Upgrade to supported PHP 8 on Laravel when the code is fundamentally sound and your team works in PHP. It keeps the database and most of the logic, and it is usually the faster route. We rebuilt an outdated Zend application on Laravel and PHP 8 in two months for a moving company while keeping its original database; the project is described on our legacy code migration services page and now runs their custom CRM software development.
Migrate to Python with Django when your team works in Python, when the application carries reporting, data processing, automation or machine learning, or when the rewrite is unavoidable and you want the language with the broadest hiring pool. Django ships with protections against cross-site request forgery, SQL injection and cross-site scripting switched on by default, and FastAPI covers API-only services.
We build production systems on this stack. Our multi-tenant security agency platform on Python and Django turns one attendance record into client invoicing and staff payroll, with each agency's data isolated from the others and statutory rates held as configuration rather than code. It was a new build rather than a PHP migration, but it is the kind of system a migrated PHP application becomes.
For the general decision, our guide on whether to migrate or rebuild legacy code covers the trade-offs.
How a legacy PHP to Python migration runs
The migration runs in six phases, with the PHP site serving customers until the Python application has proved itself on real traffic.
1. Discovery and code audit. Inventory every PHP site and dependency, map routes, database tables and integrations, and extract the business rules hidden in the code.
2. Strategy and roadmap. Choose Django or FastAPI per component, order the modules by risk and value, and write the rollback plan first.
3. Proof of concept. Rebuild the hardest piece, typically authentication, payments or the largest integration, and prove it in Python before committing to the rest.
4. Incremental migration. Reimplement route by route behind the same URLs, with PHP and Python running side by side and traffic shifted gradually.
5. Testing and data validation. Tests around every business rule, data migrated with integrity checks, and outputs from both systems compared before cut-over.
6. Cut-over, hardening and handover. Move all traffic, retire the PHP servers, apply the hardening below, and hand over documentation and knowledge.
Small sites take weeks; large systems take months, with the first modules live well before the end. Where the application also needs purchasing, inventory and reporting in one system, the migration can become custom ERP software development rather than a like-for-like rebuild.
Security hardening that comes with the migration
A new stack removes the vulnerability of the week; hardening is what keeps the next one from becoming an incident. These are the measures we apply as part of a Python migration.
Supported runtime, patched automatically. A current Python release and Django LTS, on a platform that patches the operating system without a ticket.
Django's defaults left on. CSRF protection, ORM-based queries that prevent SQL injection, template auto-escaping against XSS, and clickjacking middleware, none of them disabled for convenience.
Dependency scanning in the pipeline. Every build checks packages against known vulnerabilities and fails the deploy on a critical finding.
Secrets outside the code. Keys, passwords and tokens in a secrets manager, never in the repository or a file on the server.
Web application firewall and rate limits. A WAF in front of the application and rate limits on login, search and every public endpoint.
Least privilege. Database roles limited to what the application needs, and no shared administrator accounts.
Security headers and managed TLS. Content security policy, HSTS and the standard headers, with certificates renewed automatically.
Logging, alerting and tested restores. Centralised logs, alerts on failed logins and unusual traffic, and restores that are rehearsed rather than assumed.
A written patch process. Who reads advisories, how fast a fix ships, who signs off, so the next PHP2Shell is a routine release.
How Fly IT Solution can help
We migrate legacy PHP applications to Python with Django or to supported PHP 8 with Laravel, and we harden what we deliver. The legacy code migration engagement starts with a free assessment: your PHP inventory, your exposure to PHP2Shell and the advisories before it, and a phased plan with costs.
Projects start within 48 hours of agreement, run with the existing site live, and end with documentation and knowledge transfer. If you need Python capacity on an existing team rather than a project, you can hire dedicated developers who work your hours.
If your site is on PHP 7.4, 8.0 or 8.1, patch what you can this week and then request a free migration assessment. The inventory from the NCSC's first step is all you need to bring.
Frequently asked questions
What is PHP2Shell and why does it matter?
PHP2Shell is the collective name for CVE-2026-109618 and CVE-2026-109619, two PHP flaws fixed on 21 October 2026 that let an attacker run code on a web server with one unauthenticated request. Each is scored 9.2 on CVSS 4.0. It matters because the UK's National Cyber Security Centre has said any version of PHP is affected and that systems which cannot be updated should be taken offline, which leaves businesses on end-of-life PHP with no supported fix.
Which PHP releases contain the PHP2Shell fix?
PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35 contain the fix, and Linux distributions have shipped patched packages that may keep an older version number. PHP 7.4, 8.0 and 8.1 are out of support; they got a minimal source backport aimed at teams that compile PHP themselves and will receive nothing for future vulnerabilities. Apache with mod_php is the configuration researchers describe as most exposed.
Do I need to migrate off PHP, or is patching enough?
If you run a supported PHP 8 branch and your application works on the fixed release, patching closes this hole. Migration becomes the answer when patching is not available to you: an end-of-life version, code that breaks on modern PHP, or an application your team cannot safely change. Those sites will face the next advisory in exactly the same position, and moving to Python with Django or to supported PHP 8 with Laravel ends the cycle.
How do you migrate a legacy PHP website to Python?
In phases, with the old site live until the new one has proved itself. We audit the code and database, write tests around the business rules that must survive, rebuild the application in Django or FastAPI route by route behind the same URLs, migrate the data with integrity checks, run old and new side by side, and cut over with a rollback plan. A small site is typically weeks of work; a large system is months, with the first modules live early.
Should I migrate to Python or just upgrade to modern PHP?
Stay on PHP and upgrade to a supported PHP 8 release on Laravel when the codebase is sound and the team's skills are in PHP: it is quicker and keeps the database and most of the logic intact. Choose Python when the team already works in it, when reporting, data processing, automation or machine learning are a large part of the application, or when a rewrite is unavoidable and you want the broadest hiring pool. Django's defaults guard against CSRF, SQL injection and cross-site scripting. Fly IT Solution delivers either path and advises per project.
What security hardening goes with a PHP to Python migration?
A current Python release and Django LTS patched automatically, Django's built-in CSRF, SQL injection and XSS protections left enabled, dependency scanning that fails a build on a critical finding, secrets held in a secrets manager rather than the code, a web application firewall with rate limits on public endpoints, least-privilege database roles, security headers with managed TLS, centralised logging with alerting and rehearsed restores, and a written patch process with named owners.
How does Fly IT Solution handle a legacy PHP to Python migration?
With a free assessment of your PHP footprint and exposure, then a roadmap, a proof of concept on the riskiest component, route-by-route migration to Django or FastAPI with the PHP site still live, data migration with integrity checks, and a cut-over with rollback, hardening and handover. Work begins within 48 hours of agreement. We build multi-tenant Python and Django platforms, including a security agency management system with per-tenant data isolation, and we have also rebuilt a Zend application on Laravel and PHP 8 for clients who are better served staying on PHP.




