Detection Engineering

Hunting the Webshell After a File-Upload RCE: Detecting the Joomla and ColdFusion Wave

Dark cyberpunk illustration of a shadowed server rack with one intake slot glowing orange while a faint hand slips a glowing shard through it, cyan data traces around it.

An unauthenticated attacker can drop a working webshell on a public Joomla or Adobe ColdFusion site in the time it takes to send one HTTP POST. That is not a projection. On the Page Builder CK flaw now tracked as CVE-2026-56290, responders found the first shell at /media/com_pagebuilderck/gfonts/bhup.php, and exploitation was already running on June 27 - days before the CVE went public. Adobe ColdFusion's path-traversal bug, CVE-2026-48282, was exploited within hours of disclosure. By the time you read the advisory, patch, and reboot, the shell you needed to find has been sitting in your web root for a week.

CISA added four of these to its Known Exploited Vulnerabilities catalog on July 7, and two more Joomla extension upload flaws (Balbooa Forms, iCagenda) on July 10. The vendors shipped patches; that part is handled. The part almost nobody is writing about is the one that decides whether you actually got breached: the attacker got in before the patch existed, and patching a file-upload bug does nothing to a PHP file already sitting on disk. This is a detection problem now, and you can close it out today with tools you already have.

Who has to hunt, and who can close this tab

Run the hunt if any public site you own or manage runs Joomla with SP Page Builder (fixed in 6.6.2), Page Builder CK (fixed in 3.6.0), the Balbooa Forms or iCagenda extensions, or an internet-reachable Adobe ColdFusion server. Those are the products CISA flagged as under active exploitation. Patching the day the advisory dropped does not clear you: if you never swept the filesystem afterward, you are still exposed to whatever landed in the exploitation window. The fix locks the door behind an intruder who may already be inside.

If you run none of these - no Joomla, no ColdFusion, no forgotten marketing microsite a contractor stood up three years ago - this wave does not touch you, and you can stop reading here. Keep the pattern, though. Unauthenticated file upload leading to remote code execution is one of the most reliable ways onto a small business's public infrastructure, and the vulnerable product changes every few weeks. The hunt below works for the next one too.

Know the exploit signatures before you grep

Blind hunting produces noise. Each of these bugs leaves a distinct request pattern and, usually, a distinct file. Anchor your search on the specifics the reporting - The Hacker News and SecurityWeek - published alongside the CISA advisory.

SP Page Builder (CVE-2026-48908)

Exploitation runs through a POST to index.php?option=com_sppagebuilder&task=asset.uploadCustomIcon. A successful hit uploads a dangerous file and, in observed cases, creates a Joomla Super User account. Two things to hunt: requests to that endpoint from before you patched, and any administrator account you cannot explain.

Page Builder CK (CVE-2026-56290)

Public writeups pin the dropped shell to /media/com_pagebuilderck/gfonts/, first sample named bhup.php and keyed on a $_POST['_upl'] parameter. Filenames rotate; the directory and the upload behavior do not. Any .php file under /media/ deserves an immediate look, because that tree is meant to hold fonts and images and never executable code.

Adobe ColdFusion (CVE-2026-48282)

This one is a path traversal that reaches arbitrary code execution in the context of the ColdFusion service account. There is no single canonical artifact: the payload runs as CFML or drops a JSP/CFM file wherever the traversal lands. Hunt the ColdFusion request logs for traversal sequences and the webroot for recently written .cfm, .cfml, and .jsp files.

Step one: find the instances you forgot you own

You cannot hunt a server you do not know is running. The most common reason these bugs turn into breaches at small companies is a public site nobody remembers - a campaign landing page, an old staging box, a subsidiary's Joomla install. Before you touch a log, enumerate what is actually exposed. Our open-source surface-mapping tool scopecheck resolves a domain list to live hosts and fingerprints the stack, but a short loop gets you the same answer for a single site:

# Is this Joomla, and which builder is installed?
curl -s https://example.com/administrator/manifests/files/joomla.xml | grep -i version
curl -s -o /dev/null -w "%{http_code}\n" \
  "https://example.com/index.php?option=com_sppagebuilder"

# Probe for the Page Builder CK media path
curl -s -o /dev/null -w "%{http_code}\n" \
  https://example.com/media/com_pagebuilderck/

# Is ColdFusion answering on this host?
curl -sI https://example.com/CFIDE/administrator/ | head -n 1

A 200 on a builder endpoint or the /CFIDE/ path tells you the product is present and reachable. Feed the whole domain portfolio through the loop, not just the flagship site. The forgotten host is the one that gets you.

Hunt the request side: what the web logs remember

The exploit is an HTTP request, so your access logs hold the first evidence even after the shell is deleted. Pull every log you have back to at least June 20 - the Page Builder CK activity predates the CVE by a week, and retention is the only reason you will catch it.

# The SP Page Builder upload endpoint and the CK media path
grep -iE "asset\.uploadCustomIcon|com_pagebuilderck" /var/log/nginx/*access.log*

# POST that wrote a .php into an asset dir, then a GET to run it
awk '$6 ~ /POST/ && $7 ~ /(media|images|assets)\/.*\.php/' access.log
awk '$6 ~ /GET/  && $7 ~ /\/media\/com_pagebuilderck\/.*\.php/' access.log

# ColdFusion traversal markers
grep -iE "\.\./|%2e%2e%2f|/CFIDE/" /opt/coldfusion/cfusion/logs/*.log

The high-signal pattern is a POST returning 200 to an upload endpoint, immediately followed by GET requests to a new .php or .cfm path in a directory that should serve only static assets. Note the source addresses. Reporting tied early ColdFusion exploitation to the IP 103.207.14.220; treat any address that hit your upload endpoint as suspect and pivot on it across every log source you keep.

A Sigma rule for the upload-to-execute pattern

title: Webshell Written to Joomla/ColdFusion Static Asset Path
logsource:
  category: webserver
detection:
  upload:
    cs-uri-stem|contains:
      - '/media/com_pagebuilderck/'
      - 'task=asset.uploadCustomIcon'
  shell_exec:
    cs-uri-stem|re: '/(media|images|assets)/.*\.(php|cfm|cfml|jsp)$'
  condition: upload or shell_exec
level: high

Hunt the artifact side: what is sitting in your web root

Logs tell you a request happened; the filesystem tells you what it left behind. A webshell is a file that does not belong, usually dropped into a directory full of files that all share an age and an owner. That makes it findable.

# Any PHP under a media/upload tree is suspicious by definition
find /var/www -type f -name "*.php" \
  \( -path "*/media/*" -o -path "*/images/*" -o -path "*/tmp/*" \)

# Files written inside the exploitation window (adjust the date)
find /var/www -type f \( -name "*.php" -o -name "*.cfm" -o -name "*.jsp" \) \
  -newermt "2026-06-20" -printf "%TY-%Tm-%Td %p\n" | sort

# The behaviors a dropper needs, including the CK shell's _upl handler
grep -rlE "eval\(|assert\(|base64_decode\(|\\\$_(POST|GET|REQUEST)\[" \
  /var/www --include="*.php"

The last query catches the $_POST['_upl'] handler in the Page Builder CK shell and most commodity PHP droppers, which lean on eval, assert, or base64_decode over attacker-controlled input. Expect a handful of false positives from legitimate plugins. A shell in /media/ that was written last week and is owned by the web-server user will not be one of them. Sort your find results by modification time and read from the newest down: the dropper and any second-stage files it pulled will cluster together in a tight window, right around the POST you already flagged in the access log.

If you keep file hashes - and this wave is the argument for starting before you need them - diff the current web root against a known-good manifest. Our log-triage helper authlog folds the access log and the filesystem findings into one timeline, so you can read the upload POST and the file it wrote side by side instead of correlating them by hand.

Make the hunt a standing detection, not a one-time sweep

Running these commands once cleans up today's wave. It does nothing for the one that lands next month against a product not on this list. The durable control is continuous file-integrity monitoring on your web roots, wired to alert the moment an executable file appears where only static assets belong. osquery gives you this for free on Linux and Windows; a file-events query on the media and upload directories turns "someone dropped a shell" into a real-time alert instead of an archaeology project.

-- osquery: file_events on web-root asset directories
-- (pair with a file_paths config for /var/www/**/media/** etc.)
SELECT target_path, action, mtime, size, sha256
FROM file_events
WHERE category = 'webroot_assets'
  AND (target_path LIKE '%.php'
    OR target_path LIKE '%.cfm'
    OR target_path LIKE '%.jsp');

Feed those events to whatever you use to read logs - a full SIEM if you have one, a flat file and a nightly cron job if you do not. The control that matters is simple: a new .php in /media/ produces a human-visible signal within minutes, rather than whenever someone next happens to look. Scope the watch to directories that should only ever hold static content, so a routine plugin update does not bury the one write that matters. That single alert would have turned every CVE in this wave from a week of undetected access into a same-day response.

Diff the web root before you trust the patch

Patching SP Page Builder, Page Builder CK, and ColdFusion closes the way in. It does not tell you whether someone already walked through it. For every instance you found in step one, do three things this week: pull the access logs back to June 20 and hunt the upload endpoints, sweep the filesystem for executable files in asset directories, and stand up file-integrity monitoring so the next drop trips an alarm on the way in. If you find a shell, treat the host as compromised - rotate the ColdFusion and database credentials it could reach, and rebuild the box rather than delete-the-file-and-hope.

If you want a second set of hands on the hunt, or help wiring web-root monitoring into a workflow a small team can actually keep running, that is the work we do. Our detection and DFIR tooling is open source and on GitHub - start there, or book a session and we will walk your environment with you.

Want to try our open-source security tools?

We build open-source tools that automate the tedious parts of detection and response - external surface mapping with scopecheck, log-and-artifact triage with authlog. Browse them on GitHub, or book a session to talk through hunting and monitoring your public web infrastructure.