October 20 – 21, 2026 · PHP2Shell
Patched before sunrise.
PHP2Shell was two critical flaws in PHP itself, the language behind roughly three million websites, and attackers were testing them days before anyone could patch. Two of our servers were too old to update the normal way. This is how the YPIC IT team kept ISDS, Program, Contracts, Timesheets and ypic.com safe in one night, with no data lost.
PHP2ShellCVE-2026-109618CVE-2026-109619CVSS 9.2 · remote code execution, no login needed
Close the doors first. Then patch.
We couldn't wait for a fix that would never come for our oldest servers, so we protected first and repaired second. This is the order we worked in.
- InventoryOct 20 · 8:30 PM
- Full backup9:48 PM · 83 GB, verified
- Close the doors9:52 PM · offices and VPN only
- Temporary protectionsOct 21 · 7:00 AM
- Check for intruders7:00 AM · clean
- Patch ypic98:05 AM · PHP 7.4.34-dev
- Move ypic.comMorning · patched server
- Open the doors11:00 AM · all systems back
The world that night
Researchers named the pair of flaws PHP2Shell, and several compared it to Log4Shell. Attackers did not wait for the official announcement.
First exploit attempts against internet honeypots, while the flaws were still secret.
Amazon Threat IntelligenceThe PHP team gives advance notice. Details leak online the same day, and proof-of-concept exploits start circulating.
PHP.net · Amazon · SecurityWeekThousands of exploit attempts in the ten hours before the announcement.
CloudflareFixes ship for PHP 8.2 to 8.5. Older versions get no package, only source-code backports for 7.4, 8.0 and 8.1.
PHP.netAttempts jump to tens of thousands within 45 minutes, hundreds of thousands within two hours, then millions. SANS raises its InfoCon to yellow, and CISA urges everyone to patch.
Cloudflare · SANS ISC · CISAExploitation is broad but sloppy: many public exploits don't work, crash servers, or are fakes.
watchTowr · JFrog
How our response lined up with the experts
Turn off session upload progress
On ypic9 at 7 AM, before the patch was installed.
Limit request size
The web server rejects anything over 8 MB before PHP sees it.
Don't advertise PHP
The server no longer tells visitors which PHP version it runs.
Patch, then look for compromise
Patched by 8:05 AM. File and log checks found nothing.
Limit what the web server can do
PHP can no longer run shell commands.
Know where you run PHP
A full inventory of ypic9 within the first hour.
Sources: PHP.net advisory SANS ISC diary SecurityWeek CISA alert
The full story
- Before we knew
Attacks before the announcement
Four days before any fix existed, someone was already testing exploits against internet honeypots. Nobody outside the PHP team and its partners knew yet, and neither did we.
- The night
The alert
PHP.net warned that a critical fix was coming the next morning, and details were already leaking. Two of our servers could not be patched the normal way: ypic9, home of ISDS, Program, Contracts and our other internal systems, ran a PHP version past end of life, and ypic7, which served ypic.com, ran a PHP version that would get no fix at all.
We started with an inventory of everything ypic9 runs, so we knew exactly what we had to protect.
Back up first
Before changing anything, we made a full backup of ypic9: every line of code, every database, user accounts and server settings, and tested every file. Making it showed that our nightly backup could not see six databases. We fixed that the same day, and later copied this backup off-site to the MLK server.
DONE · 83 GB · all files OKClose the doors
A firewall rule limited our systems to the offices and the VPN. Staff working from home lost access for a few hours. The logs later proved the timing: the last outside visitor reached ypic9 at 9:52 PM, about nine hours before the official disclosure, and nothing in those last hours looked like an attack.
[20/Oct/2026:21:52:44] last outside request · then 0 until reopening- The morning
The patch ships, and so do the attacks
The fix and full advisory came out, and attacks around the world jumped from thousands to hundreds of thousands within two hours. Our doors were already closed. We applied the advisory's temporary protections, disabled PHP's shell commands, and searched for signs of a break-in: no web shells, no unexpected files, no crashes, no suspicious requests. We also had Plan B ready: ISDS and Contract running on a separate server with a current PHP.
web shells: 0 · unexpected files: 0 · crashes: 0Patch what couldn't be patched
ypic9 was one of the roughly one million servers on end-of-life PHP. No package existed for it, but the PHP security team published the fix as source code. We checked it, built it on ypic9 and swapped it in, with the old version kept for rollback. All fourteen main sites answered normally.
PHP/7.4.34-dev configured -- resuming normal operationsMove the website
ypic7 had no fix to install, so we moved ypic.com to the ypic portal server, which had received its PHP update that morning, and tested every page before the switch.
Open the doors
With everything patched and tested, we removed the block and told staff that all systems were back. Attacks were still arriving by the millions worldwide. Now they met a patched server. A test from outside the building confirmed only the websites are reachable from the internet.
- After
Leave it better than we found it
We archived and removed 179 old copies of PHP files from the web folder, some of them old login pages saved before a security fix. We retired six unused databases and three unused database accounts after checking that nothing used them. The nightly backup now covers every database, is readable by administrators only, and keeps a copy of the server settings. Web logs now rotate weekly, and the server no longer advertises its PHP version.
179 files · 6 databases · 3 accounts · logs 2.3 GB → 85 MB
The hardest part was patching a server with no patch.
ypic9 runs a PHP version that reached end of life years ago, on an operating system that no longer receives packages. The official fixes only covered PHP 8. For servers like ours, the normal answer was "upgrade first", and there was no time for that.
The PHP security team published the fix as source code for older versions. That meant building PHP ourselves, on a production server, with the exact same features as before, on the morning attacks were peaking.
So we wrote down every step before taking it, and made sure each one had a way back. The swap itself took about ten seconds, and every site answered normally afterwards.
- ACompare the fix with the official last release: 18 files changed, all where the advisory pointed.
- BBuild it on ypic9 with the same twelve extensions and the same settings as before.
- CTest the new build: identical extensions, database connection, images, Spanish text and encryption.
- DSwap it in safely, with the original kept for a ten-second rollback.
- ECheck every main site, then have staff test ISDS, CRS, Program, Contract and email.
- Every step was checked before the next one started.
How we worked
We handled this as one IT team, on three fronts at the same time, so that no single step held up the others.
Protect ypic9
The inventory, the backup, closing the doors, the patch, the break-in checks and the cleanup afterwards.
Move ypic.com
The website moved from ypic7 to the patched ypic portal server, with every page tested before the switch.
Plan B and the off-site copy
ISDS and Contract built on a current PHP version as a fallback, and the backup copied to the MLK server.
What changed
A patched server
ypic9 runs a patched PHP, locked so an update can't bring the old one back.
Fewer ways in
PHP can't run shell commands, oversized requests are refused, and the server no longer advertises its version.
A modern home for ypic.com
The website runs on an up-to-date server that receives security updates.
Backups that cover everything
Every database, every night, readable by administrators only, with a copy of the server settings.
Less clutter
Old code copies, unused databases and unused accounts are gone, and logs rotate every week.
What we learned
Act on the warning
Attackers started before the disclosure. We used the advance notice to close the doors first.
Know where you run it
The hardest part of PHP2Shell worldwide was finding every PHP server. Our inventory took an hour because we went looking right away.
Back up before you touch anything
The backup protected us, and making it showed gaps we didn't know we had.
Old systems are the real risk
About a million servers worldwide had no official fix, and ours were among them. Replacing them is the long-term answer.
Every step needs a way back
We tested the patched build before installing it and kept the original ready, so a mistake would have cost seconds, not hours.
Write it down
Notes taken during the night became the report, the staff emails, and this page.