← Back to Feed CACHED · 2026-09-29 20:41:03 · CACHE_KEY CVE-2026-48907
CVE-2026-48907 · CWE-284 · Disclosed 2026-06-05

Joomla Content Editor (JCE) Unauthenticated Remote Code Execution via Profile Import

ASSESSED — NOISGATE
Vendor
—
—
—
Reassessed
—
—
—
Verdict: —
Do you agree?
01 · The Real Story

Someone left the server room door unlocked, the safe open, and taped the combination to the wall

CVE-2026-48907 is an unauthenticated remote code execution vulnerability in the JCE (Joomla Content Editor) extension for Joomla, affecting all versions from 1.0.0 through 2.9.99.4. It chains three independent design failures in the profile import workflow: (1) the profiles.import endpoint performs no ACL or authentication check — only CSRF validation, and the token is embedded in every public page; (2) the upload handler calls File::makeSafe() which strips filesystem-illegal characters but never validates file extensions, so shell.xml.php sails through; (3) the code explicitly passes $allow_unsafe = true to File::upload(), disabling Joomla's built-in extension blacklist. An attacker sends three HTTP requests — harvest the CSRF token, POST a PHP webshell to /index.php?option=com_jce&task=profiles.import, then GET the uploaded file from /tmp/ — and owns the web server. The file lands in a web-accessible directory with its .php extension intact. No credentials, no user interaction, no special network position required.

The vendor's CVSS 3.1 score of 9.8 (and CVSS v4 score of 10.0) is not inflated — if anything, the v3.1 label undersells the real-world urgency. This is a zero-friction, pre-auth RCE that has been weaponized into automated scanning campaigns within days of disclosure. CISA added it to the KEV catalog on 2026-06-16 with a 3-day remediation deadline for FCEB agencies. Multiple public PoCs exist, a nuclei template is published, and exploit-kit operators are deploying webshells, cryptominers, and botnet enrollment payloads at scale. The roughly 2.5 million active Joomla installations — many running JCE as the most popular editor extension — represent a massive, internet-facing attack surface with near-zero exploit complexity.

"Unauth RCE in 3 HTTP requests, actively exploited, KEV-listed — patch now."
02 · The Attack Path

5 steps from start to impact.

STEP 01

Discover vulnerable Joomla+JCE target

The attacker uses mass-scanning tools (nuclei, httpx, or Shodan/FOFA dorks) to identify Joomla sites running JCE ≤ 2.9.99.4. The JCE version can be fingerprinted from its JavaScript/CSS asset paths or by probing the com_jce component endpoint. Automated campaigns have been sweeping the internet since early June 2026.
Conditions required:
  • Target runs Joomla with JCE extension ≤ 2.9.99.4
  • Target is reachable over HTTP/HTTPS
Where this breaks in practice:
  • None — Joomla sites are inherently internet-facing, and JCE is one of the most popular Joomla extensions
Detection/coverage: Nuclei template CVE-2026-48907.yaml in projectdiscovery/nuclei-templates. Shodan/Censys queries for Joomla+JCE fingerprints.
STEP 02

Harvest CSRF token from public page

The attacker sends a GET request to any public page on the Joomla site and extracts the CSRF token from the HTML meta tags or inline JavaScript. Joomla embeds this token in every page served to every visitor, including unauthenticated guests. This is trivial to automate and adds no real barrier.
Conditions required:
  • Target serves public pages (virtually all Joomla sites)
Where this breaks in practice:
  • None — the CSRF token is public by design in Joomla's architecture
STEP 03

Upload PHP webshell via profile import endpoint

The attacker sends a multipart POST to /index.php?option=com_jce&task=profiles.import with the harvested CSRF token and a file named with a dual extension (e.g., shell.xml.php). The endpoint performs no authentication check (Weakness 1), File::makeSafe() does not strip the .php extension (Weakness 2), and File::upload() is called with $allow_unsafe = true (Weakness 3). The file is written to the web-accessible /tmp/ directory with its PHP extension intact. Weaponized tools: grayxploit PoC, 0xgh057r3c0n PoC, ywh-jfellus PoC, bayu06802 nuclei+Python toolkit.
Conditions required:
  • JCE profiles.import endpoint is accessible (default in all JCE installs)
  • Web server allows PHP execution in /tmp/ (default Apache/Joomla configuration)
Where this breaks in practice:
  • A WAF rule blocking multipart POSTs to profiles.import would stop this, but almost no one has that rule pre-configured
  • Server-level config disabling PHP in /tmp/ would break execution, but this is not a Joomla default
Detection/coverage: WAF signatures for task=profiles.import with file upload payloads. IDS rules matching the specific URI pattern.
STEP 04

Execute webshell for full server compromise

The attacker sends a GET request to /tmp/shell.xml.php (or whatever filename they chose). Apache processes the file using the .php handler based on the final recognized extension. The webshell executes with the permissions of the web server process (typically www-data or apache). From here, the attacker can execute arbitrary commands, read database credentials from configuration.php, pivot to the database, exfiltrate data, or establish persistent backdoor access.
Conditions required:
  • PHP execution is enabled for the /tmp/ directory
  • Web server process has sufficient OS-level permissions
Where this breaks in practice:
  • If the server runs PHP-FPM with open_basedir restrictions covering /tmp/, execution may fail — but this is uncommon in default Joomla hosting setups
Detection/coverage: File integrity monitoring (FIM) detecting new .php files in /tmp/. Web server access logs showing requests to /tmp/*.php. YARA rules for common webshell patterns.
STEP 05

Post-exploitation: lateral movement and persistence

With a webshell on the Joomla server, the attacker reads configuration.php to obtain MySQL credentials, enumerates the local network, and attempts lateral movement via database pivots, SSH key harvesting, or exploiting internal services reachable from the DMZ. Observed payloads in the wild include cryptominers, botnet agents, defacement scripts, and additional webshells for persistence. Rogue JCE profiles (named with pattern J followed by six digits, e.g., J938560) are created for persistent re-entry.
Conditions required:
  • Initial webshell execution succeeded
  • Internal network is reachable from the web server
Where this breaks in practice:
  • Network segmentation between web DMZ and internal networks limits lateral movement
  • EDR on the web server host can detect post-exploitation activity
Detection/coverage: Hunt for JCE profiles matching J[0-9]{6} pattern. Monitor for new PHP files in web-accessible directories. Database audit logs for credential access.
03 · Compensating Control

1
CRITICAL 9.8→LOW 2.0
SEVERITY REDUCED
Block or restrict the profiles.import endpoint at the WAF/reverse proxy — Add a WAF rule to deny any POST request matching task=profiles.import on the com_jce component. This breaks the upload step (Step 3) of the attack chain entirely without affecting normal JCE editor functionality, since profile import is an admin-only operation that legitimate users access through the Joomla backend, not the frontend. Per the noisgate mitigation SLA for CRITICAL, deploy within 3 days. Cloudflare, Akamai, and Imperva have pre-built virtual patches available — enable them immediately.
2
CRITICAL 9.8→MEDIUM 5.0
SEVERITY REDUCED
Disable PHP execution in the Joomla /tmp/ directory — Add a .htaccess file (Apache) or location block (Nginx) to the Joomla /tmp/ directory that disables PHP execution (php_flag engine off for Apache, location ~* \.php$ { deny all; } for Nginx). This breaks Step 4 — even if the file is uploaded, it cannot execute. Deploy within 3 days per noisgate mitigation SLA for CRITICAL. This is a quick server-level change that does not require a Joomla extension update.
3
CRITICAL 9.8→IGNORE 0.0
SEVERITY REDUCED
Upgrade JCE to ≥ 2.9.99.6 — This is the definitive remediation. Version 2.9.99.5 fixes the core access control failure; 2.9.99.6 adds hardening. The upgrade closes all three weaknesses in the chain. Per the noisgate remediation SLA for CRITICAL, apply the patch within 90 days — but given active exploitation and KEV listing, treat this as immediate (within hours to days). Test in staging and deploy to production as an emergency change.
4
CRITICAL 9.8→CRITICAL 9.8
Hunt for existing compromise indicators — Search for rogue JCE profiles matching the pattern J[0-9]{6} (e.g., J938560, J991471). Scan /tmp/ and other web-accessible directories for unexpected .php files. Review web server access logs for POST requests to task=profiles.import and GET requests to /tmp/*.php. Check configuration.php access patterns for credential harvesting. This does not reduce vulnerability but ensures you catch attackers who have already exploited the flaw. Execute immediately alongside patching.
What doesn't work
  • Disabling Joomla user registration does not help — the vulnerability requires no Joomla account whatsoever. The exploit targets an unauthenticated endpoint, so registration settings are irrelevant.
  • IP-based rate limiting is insufficient — the full exploit chain is only 3 HTTP requests, well under any reasonable rate limit threshold. A single request per minute is enough to compromise a target.
  • Joomla core updates alone do not help — JCE is a third-party extension. Updating Joomla core without updating the JCE extension leaves the vulnerability fully exploitable.
  • CSRF token rotation / regeneration does not help — the attacker harvests a fresh token on every attempt from any public page. Shortening token lifetime adds negligible friction.
04 · Intelligence Metadata

The supporting signals.

In-the-Wild ExploitationConfirmed active exploitation. CISA added to KEV on 2026-06-16 citing active exploitation. Automated scanning campaigns observed sweeping ~2.5M Joomla sites. Payloads include PHP webshells, cryptominers, defacement scripts, and botnet enrollment. Rogue profiles with J[0-9]{6} naming pattern are a signature of the active exploit kit.
Proof-of-Concept AvailabilityMultiple public PoCs. GitHub repos: grayxploit/CVE-2026-48907 (3-request chain walkthrough), 0xgh057r3c0n/CVE-2026-48907, NoXiVaR/CVE-2026-48907, ywh-jfellus/CVE-2026-48907 (YesWeHack researcher), bayu06802/CVE-2026-48907 (Python + nuclei). Also indexed on Sploitus.
EPSS ScoreUser-supplied: 0.1619 (16.19%) at ~97th percentile. Nuclei template metadata reports 0.80425 (99.575th percentile) — likely a later snapshot reflecting KEV addition and mass exploitation. Either way, this is in the top 1% of all CVEs for predicted exploitation probability.
KEV StatusListed. Added 2026-06-16. FCEB remediation deadline: 2026-06-19 (3-day window). CISA alert.
CVSS VectorCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H = 9.8. CVSS:4.0 score = 10.0. Every base metric is at maximum severity: network-accessible, low complexity, no privileges, no user interaction, full CIA impact. The vector accurately reflects the real attack — zero friction from initial access to code execution.
Affected VersionsJCE (Joomla Content Editor) 1.0.0 through 2.9.99.4 — both Free and Pro editions. This encompasses the entire version history of the extension.
Fixed VersionsJCE 2.9.99.5 (released 2026-06-03) — core fix. JCE 2.9.99.6 (released 2026-06-08) — additional hardening. Current recommended version: ≥ 2.9.99.6. Vendor also shipped a standalone patch for sites unable to do a full extension upgrade.
Scanner / Detection CoverageNuclei template CVE-2026-48907.yaml available in projectdiscovery/nuclei-templates (verified, 3 requests, intrusive/modifying). Tenable plugin available. WAF vendors (Cloudflare, Akamai, Imperva) have deployed virtual patches.
Disclosure Date2026-06-05 (CVE published). Patch released 2026-06-03 (2 days before CVE publication). KEV added 2026-06-16.
Reporting Researcher / OrgDiscovered via YesWeHack vulnerability research team. YesWeHack writeup published same day as advisory with full technical chain analysis. Individual researcher handle: ywh-jfellus (GitHub PoC author).

Sources.

  1. CISA KEV Alert — CVE-2026-48907 Added
  2. GitHub Advisory GHSA-c3f5-4g7f-qjqj
  3. YesWeHack — Unauthenticated RCE in JCE Extension
  4. grayxploit/CVE-2026-48907 — 3-Weakness Chain PoC
  5. JCE 2.9.99.5 Security Update — Official Vendor Advisory
  6. The Hacker News — CISA Warns of Actively Exploited JCE Flaw
  7. Nuclei Template — CVE-2026-48907.yaml
  8. Tenable — CVE-2026-48907
05 · The Call

Final Verdict
= UNCHANGED to CRITICAL (9.8/10)

Why this verdict

  • Zero authentication friction: The entire chain requires no credentials whatsoever. The CSRF token — the only 'gate' — is embedded in every public page Joomla serves. This is not a gate; it is a welcome mat.
  • Trivial weaponization: The exploit requires exactly 3 HTTP requests and is fully automated in multiple public PoCs, a nuclei template, and at least one active exploit kit. Complexity is effectively zero — a script kiddie can pop a shell.
  • Massive, inherently exposed attack surface: Joomla is a web CMS — ~2.5 million active sites, and JCE is one of its most popular extensions. Unlike vulnerabilities requiring internal network access, every affected installation is reachable from the internet by design. There is no 'only 1% are exposed' argument to make here.
  • Active mass exploitation confirmed: CISA KEV-listed with a 3-day remediation deadline. Automated campaigns deploying webshells, cryptominers, and botnet agents are confirmed. This is not theoretical — it is burning right now.
  • Role multiplier: (a) *Low-value role:* Dev/staging Joomla sites — compromise is contained, blast radius is host-level. (b) *Typical role:* Production website or web application — compromise yields webshell, DB credentials, customer data, and a beachhead into the DMZ. (c) *High-value role:* Joomla instances serving e-commerce, customer portals, government services, or intranet applications — compromise leads to PII/payment data exfiltration, supply-chain risk if serving software downloads, and lateral movement into internal networks. The chain succeeds identically in all roles (no role-specific prerequisites). While Joomla is not a canonical high-value-role component (it is not a DC, IdP, or hypervisor), 100% of its installs are internet-facing by definition, and a web server compromise is the canonical initial access vector for deeper network penetration. The blast radius is host → tenant → potentially network, depending on segmentation.
  • No downward adjustments applicable: Every friction audit checkpoint returns zero friction. Attacker position: unauthenticated remote. Prerequisites: none beyond network reachability. Population exposed: 100% of installs. Modern security tool that stops it: WAF with specific rule (not default). There is no compounding downward pressure on this vulnerability.

Why not higher?

A 9.8 is already the effective ceiling for CVSS v3.1 single-system impact. The CVSS v4 score of 10.0 captures the additional subsequent-system impact. noisgate does not inflate beyond the CVSS v3.1 vector-calculated score. The only reason this isn't a flat 10.0 is the Scope metric — exploitation grants web server process privileges, not necessarily root/SYSTEM, and subsequent system impact depends on network segmentation.

Why not lower?

Every possible friction point that could justify a downgrade is absent. There is no authentication requirement, no user interaction, no complex race condition, no unusual configuration prerequisite, and no limited attack surface. The vulnerability is being actively exploited at scale with automated tooling. KEV listing with a 3-day federal deadline confirms this is as urgent as it gets. Downgrading would be professionally irresponsible.

06 · Verification

Crowdsourced verification payload.

Run this script on the Joomla web server host as any user with read access to the JCE extension files (typically root or www-data). Invoke with: sudo bash check_cve_2026_48907.sh /var/www/html where the argument is your Joomla installation root. No network access or external dependencies required.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# check_cve_2026_48907.sh — Detect CVE-2026-48907 (JCE unauthenticated RCE)
# Usage: bash check_cve_2026_48907.sh /path/to/joomla
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN

set -euo pipefail

JOOMLA_ROOT="${1:-/var/www/html}"
JCE_MANIFEST="${JOOMLA_ROOT}/administrator/components/com_jce/jce.xml"
JCE_PROFILES_CONTROLLER="${JOOMLA_ROOT}/administrator/components/com_jce/controller/profiles.php"

if [ ! -f "$JCE_MANIFEST" ]; then
    echo "UNKNOWN — JCE extension not found at ${JOOMLA_ROOT}. Verify the Joomla root path."
    exit 2
fi

# Extract JCE version from manifest
JCE_VERSION=$(grep -oP '<version>\K[^<]+' "$JCE_MANIFEST" 2>/dev/null || echo "")

if [ -z "$JCE_VERSION" ]; then
    echo "UNKNOWN — Could not parse JCE version from ${JCE_MANIFEST}."
    exit 2
fi

echo "Detected JCE version: ${JCE_VERSION}"

# Compare versions using sort -V
PATCHED_VERSION="2.9.99.5"
if printf '%s\n%s\n' "$PATCHED_VERSION" "$JCE_VERSION" | sort -V | head -n1 | grep -qx "$PATCHED_VERSION"; then
    echo "PATCHED — JCE ${JCE_VERSION} is >= ${PATCHED_VERSION}. CVE-2026-48907 is fixed."
    exit 0
else
    echo "VULNERABLE — JCE ${JCE_VERSION} is < ${PATCHED_VERSION}. CVE-2026-48907 applies."
    # Additional check: look for IOCs
    echo ""
    echo "--- IOC Hunt ---"
    if find "${JOOMLA_ROOT}/tmp" -name '*.php' -type f 2>/dev/null | head -5 | grep -q .; then
        echo "WARNING: PHP files found in ${JOOMLA_ROOT}/tmp/ — possible webshell:"
        find "${JOOMLA_ROOT}/tmp" -name '*.php' -type f -ls 2>/dev/null | head -10
    else
        echo "No PHP files found in ${JOOMLA_ROOT}/tmp/ (good)."
    fi
    # Check for rogue JCE profiles in database config
    echo ""
    echo "Recommendation: Query the database for JCE profiles matching pattern J[0-9]{6}."
    exit 1
fi