A site owner ran Joomla 5, kept it patched, and sat behind a WAF configured at a strict paranoia level. It still got hacked. Here's exactly how the attacker got in, why a WAF alone wasn't enough to stop it, and the concrete steps that would have.
What "Secure" Actually Looked Like Before the Breach
The setup wasn't careless. The site ran the latest Joomla 5 release, applied security updates regularly, and sat behind a front-end Web Application Firewall configured with a strict ruleset. On paper, that's a reasonable baseline for a small-to-medium Joomla site. It still wasn't enough, and the way it failed is worth understanding in detail because the same gap exists on a lot of Joomla installs right now.
The Attack Chain, Step by Step
Reconnaissance Through a Public Form
The attacker didn't start with an exploit. They started with the contact form, sending a sequence of SQL injection and other probing payloads to map what the site would and wouldn't reject. This is the unglamorous first stage of most real attacks: cheap, automatable, and mostly ignored because it rarely trips an alert on its own.
The Search Endpoint Becomes the Entry Point
The attacker moved on to the site's search functionality, built on Joomla's core Smart Search component (com_finder). They sent crafted query strings through the search parameter, using a syntax that gets treated as executable code by a specific class of third-party extension: plugins that let editors embed and run PHP directly inside article content, if that content ever reaches them unfiltered. Some of these requests were blocked by the WAF and came back as 403s. Others got through.
From Input to Remote Code Execution
Eventually one payload succeeded: a base64-encoded PHP snippet passed through the search query, which the code-execution plugin ran. The script rewrote defines.php, a core Joomla configuration file, installing a small remote file inclusion backdoor that accepted further PHP from a POST parameter. The site returned a 500 error and was effectively down while the attacker had persistent remote access. According to the disclosure, the attacker also probed the /administrator/ login and the site's /api endpoint, standard follow-up recon once a foothold exists, with no evidence of data exfiltration reported.
Why the WAF Didn't Stop It
A WAF filters known bad patterns in incoming requests. It caught several of the attacker's attempts and returned 403s for them. But the successful payload was encoded specifically to slip past pattern matching. Critically, the vulnerability wasn't a single clean flaw in one file. It was a chain: an input-handling quirk in a core search component, combined with a separate, unrelated plugin that was designed, by intent, to execute PHP found in content. Neither piece looks dangerous in isolation. Combined, they gave an attacker a path from a public search box to server-side code execution. A WAF is one layer. It was never going to be the only layer that mattered here.
The Extension Vendor's Response Was the Bright Spot
Once the vulnerability was reported publicly, the plugin's developer confirmed the mechanism, shipped a patched major version within days, and the issue was assigned CVE-2025-22204. That's the system working as intended on the remediation side. The more useful lesson for site owners isn't about that one vendor's response time. It's about how the disclosure happened. Publishing a working exploit chain with full request logs, in public, before a fix had shipped, put every other user of that plugin at risk in the meantime. If you ever find a real vulnerability in a Joomla extension, report it privately to the developer first, and only write it up publicly once a fix is available. That's what responsible disclosure means in practice.
A Practical Hardening Checklist
None of this requires exotic tooling. It requires treating every installed extension as part of your attack surface, not just the ones you remember are there.
- Audit anything that executes code from content. Any plugin that lets editors embed and run PHP, JavaScript includes, or raw HTML is a standing risk. Know which ones are active, restrict who can use them, and remove them if the feature isn't actually in use.
- Reduce your search component's footprint if you don't need it.
If a site doesn't rely on Smart Search, uninstalling it (test on staging first) is the more reliable move than just toggling it off in the Extensions Manager, since disabling a component doesn't reliably guarantee its frontend endpoint stops responding. If you need to keep it installed, at minimum turn off the Finder-type plugins for content you don't need indexed, so there's less for it to process.
- Review installed plugins for what they're capable of, not just whether they're enabled.
A plugin can be perfectly legitimate and still be the weak link if it was built to do something as powerful as executing arbitrary code.
- Restrict filesystem write permissions so a compromised request can't rewrite core files like
defines.phpeven if it gets that far. - Keep frequent backups, ideally more than once a day for anything business-critical, so a compromise is an inconvenience rather than a disaster.
- Check the Vulnerable Extensions List (VEL) for every extension you run, not just at install time but on an ongoing basis.
The Real Takeaway
A patched core and a WAF are necessary. They are not sufficient. This site was compromised by a combination of two individually unremarkable pieces: a search component processing input in an unexpected way, and an unrelated plugin doing exactly what it was designed to do. That combination is the actual lesson: attack surface isn't just about missing patches. It's about every capability sitting on your site, whether or not you remember it's there. If your Joomla site has already been through something like this, the follow-up question is what a cleanup actually needs to catch. See our companion piece on how a hacked Joomla site can stay hacked even after a cleanup.
Not sure whether your own Joomla site has a gap like this?
Most Joomla breaches come down to one overlooked capability, not a missing patch. I review Joomla sites for exactly this class of chained-exploit and code-execution risk, close the gaps, and harden what's left — before someone else finds them first.


