Security incidents are stressful and often stay behind closed doors. We're publishing this summary to show how we approached a real compromise on a client's production Laravel application: how we found the entry point, used logs and file analysis to understand the scope, and fixed it step by step. Our goal is to demonstrate how we work under pressure and to underline something we tell every client: regular dependency updates and basic hardening are not optional — they're the first line of defence.
What We Found
We maintain a production Laravel application that uses Livewire for dynamic front-end behaviour (booking flows, cart, forms). The site is deployed on Laravel Forge with shared storage for uploads.
The incident surfaced in two ways:
1. A Phishing Page
A page was being served at a path that does not exist in the application code — used to impersonate a trusted authority and steal credentials. The content and assets lived only on the server (under public/), not in the repository.
2. Malware Beyond the Phishing Kit
Once we started looking, we found more than a single backdoor. In Forge shared storage we discovered:
- Webshells — file-manager style backdoors and hidden PHP triggered by a secret parameter
- Cryptominer droppers — scripts that pulled and ran mining binaries; in this case XMRig mining Monero via the supportxmr.com pool to a wallet we documented (e.g.
8556M2f…) - SEO spam — hidden links and content
- Loader-style backdoors — obfuscated PHP in upload directories (blog images, avatars)
So we weren't dealing with "one hacked page" — we were dealing with an established compromise that could upload files, run commands, and mine cryptocurrency.
Sites with doorways and hidden code pay a real price beyond the obvious security risk: sensitive information can leak (attackers with shells can read config files, environment variables, databases, and customer data — with regulatory and reputational fallout), performance drops (cryptominers and extra scripts consume CPU and memory), SEO and domain reputation suffer (search engines penalise or devalue compromised sites, and trust signals erode), and sender reputation — and thus email deliverability — can be severely damaged or destroyed if the server or domain is abused for spam or phishing. Fixing the breach is only the first step; recovering rankings, inbox placement, and trust can take much longer.
How Did They Get In?
We had to answer: how did someone create a new URL and drop PHP shells in upload directories?
We ruled out the application code first. There is no route or reference to the phishing path in the repo. The app does not write arbitrary filenames like index.php or cache.php in blog or avatar folders — it only writes image files with controlled names. So the malware was placed on the server, not by normal application behaviour.
From there we looked at realistic entry points:
| Vector | Assessment |
|---|---|
| Livewire CVE (pre-3.6.4) | Very likely. The app was on Livewire 3.6.3. A critical remote code execution flaw allowed a crafted POST to /livewire/update to run code on the server — enough to write shells into public/ or shared storage. |
| Leaked or phished server/Forge access | Possible, especially for initial placement of some files. |
| Other vulnerabilities on the server | Possible; the Livewire CVE alone was enough to explain ongoing file creation. |
Conclusion: The most plausible explanation for the ongoing creation of PHP shells was exploitation of the Livewire vulnerability. The fix was to upgrade to Livewire 3.6.4+ and redeploy — which we did.
How We Responded, Step by Step
We didn't just "patch and hope." We followed a clear sequence: confirm scope, stop abuse, remove malware, fix the cause, harden.
1. Confirm the Codebase Was Clean
We searched the repository for the phishing path, backdoor patterns (eval(, base64_decode with user input, shell_exec, etc.), and any code that could write arbitrary filenames. Result: no malicious code and no feature that could have created those files. The compromise was server-side only — no poisoned commits.
2. Map Where the Malware Lived
We listed and inspected suspicious files in shared storage and the main site path: root-level webshells, miners, spam scripts, and the repeated index.php / cache.php pattern inside upload directories. We documented every path and type so we could remove them consistently and avoid deleting legitimate framework files.
3. Use Logs to Find Who Was Using the Shells
Access and error logs told us who was actively using the backdoors: specific IPs making POSTs to known shells and GETs with eval'd query strings. We also saw automated POST /livewire/update traffic, consistent with probing or exploiting the Livewire endpoint.
We recommended and applied blocking the operator IPs at Nginx or firewall level so that even if a shell remained temporarily, those actors could not reach it.
4. Remove Every Shell and Lock Down PHP Where It Shouldn't Run
We produced a delete list and safe removal steps for all root-level malware and every suspicious index.php / cache.php under shared storage and public/ subdirs — except the single legitimate Laravel public/index.php.
We also recommended a Nginx rule to block execution of PHP under /storage/. That way, even if a .php file is ever dropped there again, the server returns 403 and does not execute it. No application change was required — only server config.
5. Fix the Root Cause: Upgrade Livewire and Dependencies
We upgraded Livewire to 3.6.4+ (and to a current 3.7.x) so that the vulnerable /livewire/update behaviour is no longer exploitable. We did this on a staging site first, then deployed the same stack to production after testing.
We also ran composer audit and addressed other reported issues (e.g. Symfony HttpFoundation, league/commonmark) so that one fixed CVE didn't leave other known vulnerabilities in place.
6. Harden the App and Deployment
In parallel we removed or guarded development-only routes, hardened the sitemap route against path traversal, recommended credential rotation (Forge, SSH, DB, app keys, API keys) and 2FA on Forge and server accounts, and recommended monitoring (e.g. file-integrity checks) for unexpected .php under public/ and shared storage.
What We Want You to Take Away
One Outdated Dependency Can Be the Whole Door
In this case, one critical CVE in Livewire (a dependency the client didn't "write") was enough for an attacker to run code and drop shells. The entry point was a known, patchable issue in a popular package. That's why we treat regular dependency updates as non-negotiable: not "when we have time," but as part of every release cycle and after every security advisory.
Logs Are Your Evidence
Without access and error logs we would have been guessing. Logs showed which IPs were using the shells, that the Livewire endpoint was being hit in an automated way, and that other paths were being probed but correctly blocked. Keep logs, centralise them if you can, and know how to search them.
Blocking PHP Where It Shouldn't Run Is Cheap and Effective
Blocking execution of .php under /storage/ doesn't fix the root cause, but it greatly reduces the impact of any shell that gets dropped. Defence in depth means: even if one layer fails, the next one can still protect you.
The Business Impact Goes Beyond the Breach
Compromised sites with doorways and hidden code don't just create a security problem. Sensitive information can leak — attackers with access can read config files, environment variables, databases, and customer data, with serious regulatory (e.g. GDPR) and reputational consequences. Performance drops when cryptominers and extra scripts consume CPU and memory. SEO and domain reputation suffer when search engines penalise or devalue the site. Sender reputation and email deliverability can be severely damaged or destroyed if the server or domain is abused for spam or phishing — and recovering inbox placement can take a long time. Fixing the breach is essential; understanding and mitigating these downstream effects is part of a full response.
Staging and a Clear Checklist Prevent Mistakes
We upgraded Livewire and other packages on staging first, ran the test suite and a smoke test, and only then deployed to production. We used a checklist (remove malware, block IPs, add Nginx rules, rotate credentials, then patch and deploy) so nothing was skipped under pressure.
For Clients and Teams
If you run a Laravel (or any modern PHP) application in production:
- Schedule dependency updates (Composer and npm) and run
composer auditandnpm auditregularly. - Apply security patches for frameworks and key packages (Livewire, Laravel, Symfony) as soon as they're released.
- Harden the server: block execution of scripts in upload/shared directories; use the minimum permissions needed.
- Keep and review logs so that when something does happen, you can trace the vector and the scope instead of guessing.
We're happy to help you put a simple update and audit process in place, or to review your current setup for the same kinds of risks we saw in this incident. Security isn't a one-off; it's part of how we maintain your product.
Incident response was carried out in March 2026. Technical details are summarised; internal incident reports and path lists remain confidential.