← Back to Feed CACHED · 2026-07-13 03:56:40 · CACHE_KEY CVE-2026-56291
CVE-2026-56291 · CWE-434 · Disclosed 2026-07-09

Balbooa Forms for Joomla — Unauthenticated Arbitrary File Upload leading to RCE

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

A public form endpoint that accepts .php as if it were a JPEG, gift-wrapped for anyone with curl

Balbooa Forms is a widely deployed Joomla forms/builder extension. Through version 2.4.0, its frontend attachment upload handler took files from anonymous visitors with no authentication, no CSRF token, and no allowlist on file type or extension. An attacker POSTs a PHP payload to the form endpoint, the file lands under the site's writable uploads directory, and then a second GET executes it as the web-server user. The fix ships in 2.4.1 (released 2026-07-09); everything ≤ 2.4.0 is exploitable.

The vendor CRITICAL / 9.8 rating is accurate and if anything conservative. The vector is AV:N/AC:L/PR:N/UI:N with full CIA impact, and CISA added it to KEV on the same day as disclosure because in-the-wild exploitation was already underway. There is no meaningful friction — no auth, no user interaction, no rare configuration. This is a single-request unauth RCE against internet-facing PHP.

"KEV-listed unauthenticated PHP upload → RCE with a single HTTP request. Patch tonight, hunt for webshells tomorrow."
02 · The Attack Path

5 steps from start to impact.

STEP 01

Enumerate Joomla sites running Balbooa Forms

Attacker fingerprints Joomla installs via /administrator/manifests/files/joomla.xml, then greps rendered pages for Balbooa Forms markers (com_baforms, baforms-wrapper, asset paths under /components/com_baforms/). Mass scanning with httpx + nuclei templates finds candidates in minutes.
Conditions required:
  • Target site is internet-reachable
  • Balbooa Forms component installed and enabled
Where this breaks in practice:
  • Sites behind WAF with virtual-patching may not respond to fingerprint markers
Detection/coverage: Shodan/Censys queries for com_baforms in HTML bodies produce the candidate list; nuclei has templates for Joomla component enumeration.
STEP 02

POST malicious file to unauth upload endpoint

The frontend attachment upload accepts anonymous multipart uploads. Attacker sends a multipart/form-data POST with a .php file (or double-extension like shell.php.jpg depending on server handler config). No session, no token, no MIME validation. Public PoCs are circulating; curl one-liners are trivial.
Conditions required:
  • Form containing an attachment field is published on any public URL
  • PHP writable upload directory
Where this breaks in practice:
  • Some deployments front Joomla with ModSecurity/CRS rules blocking .php in multipart bodies
  • Cloudflare/Sucuri WAF virtual patch may drop the request
Detection/coverage: Web logs show POST to /index.php?option=com_baforms&... with Content-Type: multipart/form-data; EDR on the LAMP host sees new .php files appearing under uploads/.
STEP 03

Locate the dropped webshell

Balbooa stores attachments under a predictable path (typically /images/baforms/ or /media/com_baforms/uploads/). Response body often echoes the stored filename. Attacker requests the file directly.
Conditions required:
  • Uploaded file lands under docroot
  • Apache/Nginx configured to execute .php in that directory
Where this breaks in practice:
  • Hardened configs block PHP execution in uploads via .htaccess or nginx location deny — but default Joomla installs do NOT ship this
Detection/coverage: Access log shows GET to newly-created file in uploads path, high entropy filename, PHP mimetype in response.
STEP 04

Execute as web-server user (RCE)

The GET triggers PHP execution as www-data/apache/nobody. Attacker gains a foothold via China Chopper, WSO shell, or p0wny-shell. From here: exfil configuration.php (DB creds, secret), pivot to Joomla admin via password reset in DB, mine credentials, plant persistence.
Conditions required:
  • PHP handler enabled for the upload directory
Where this breaks in practice:
  • SELinux/AppArmor profiles limiting httpd write/exec
  • PHP disable_functions blocking exec/system/passthru
Detection/coverage: EDR flags shell spawn from httpd/php-fpm; process tree apache2 → sh → curl/wget is a classic webshell tell.
STEP 05

Post-exploitation and lateral movement

Attacker reads configuration.php for DB creds, dumps #__users, adds a Super User row or resets an existing one. From admin panel they enable Joomla template editing to establish persistent RCE that survives extension removal. Also common: SEO-spam/skimmer injection, or pivoting to backend via credential reuse.
Conditions required:
  • Local DB access from webshell
  • Reused credentials or shared hosting
Where this breaks in practice:
  • Site isolation on managed hosting
  • Read-only filesystem for templates
Detection/coverage: Joomla audit log shows new Super User, template file mtime changes, unexpected outbound HTTP.
03 · Compensating Control

1
Disable the Balbooa Forms component in Joomla until 2.4.1 is applied — Site Admin → Extensions → Manage → set com_baforms to Disabled. This zeroes the attack surface immediately. Deploy within 3 days per noisgate mitigation SLA — but given KEV, do it in the next maintenance window today.
2
Add a WAF virtual patch blocking multipart POSTs to Balbooa endpoints with executable extensions — In Cloudflare/AWS WAF/ModSecurity, block requests to /index.php?option=com_baforms* that contain Content-Disposition: filename= with .php, .phtml, .phar, .php3-8, .pht, .inc. Deploy within 24 hours if you cannot disable the component.
3
Deny PHP execution in Joomla upload directories — Drop .htaccess with <FilesMatch \.ph(p[3-8]?|tml|ar)$> Require all denied </FilesMatch> under /images/, /media/, and any Balbooa upload path. For nginx add location ~ ^/(images|media)/.*\.php$ { deny all; }. Do this now and keep it after patching.
4
Hunt for existing webshells — KEV-listed with pre-patch exploitation means you may already be popped. Grep uploads directories for <?php, unusual filenames (high entropy, mixed case), files newer than 2026-06-01, and Joomla #__users for unexpected Super Users. Run within 24 hours.
5
Rotate secrets in configuration.php and DB creds — If you find any indicator of compromise, treat DB credentials, Joomla secret, API tokens, and any admin passwords as burned. Rotate before restoring the patched site.
What doesn't work
  • Relying on EPSS 0.00836 as low-risk — EPSS is a lagging model; KEV is the authoritative signal here.
  • Reverse proxy / Cloudflare in front without a specific rule — a passthrough CDN does nothing against a legitimate-looking multipart POST unless you write the virtual patch above.
  • Rate limiting — one HTTP request is enough for RCE. Rate limits don't help.
  • Disabling Joomla registration — the endpoint is unauth on the frontend, not the admin panel.
04 · Intelligence Metadata

The supporting signals.

In-the-wild statusActively exploited — added to CISA KEV on disclosure day (2026-07-09). Zero-day exploitation confirmed before patch shipped.
Public PoCPoC details published by mySites.guru; single curl one-liner reproducing upload is circulating in security Twitter/Mastodon.
EPSS0.00836 (low percentile despite KEV — EPSS lags reality here; treat KEV as the ground truth)
KEVListed 2026-07-09, FCEB due date per BOD 22-01 is 3 weeks out
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H = 9.8 CRITICAL — no auth, no interaction, network reachable, full CIA
Affected versionsBalbooa Forms ≤ 2.4.0 on Joomla 3.x / 4.x / 5.x
Fixed version2.4.1 (released 2026-07-09)
Exposure populationBalbooa Forms is one of the top form extensions in the Joomla Extensions Directory; Shodan/Censys queries for com_baforms return tens of thousands of hosts
Disclosed2026-07-09 (coordinated with vendor patch)
CWECWE-434 — Unrestricted Upload of File with Dangerous Type

Sources.

  1. mySites.guru — Balbooa Forms RCE (CVE-2026-56291)
  2. SecurityAffairs — CISA adds iCagenda and Balbooa Forms to KEV
  3. NVD — CVE-2026-56291
  4. CIRCL Vulnerability-Lookup — CVE-2026-56291
  5. THREATINT — CVE-2026-56291
  6. Balbooa Joomla Forms Changelog
  7. Joomla Extensions Directory — Balbooa Forms
  8. CISA KEV Catalog
05 · The Call

Final Verdict
= UNCHANGED to CRITICAL (9.8/10)

Why this verdict

  • No auth, no CSRF, no MIME check — the vendor advisory and PoC both confirm the endpoint accepts anonymous PHP uploads. There is no prerequisite compromise stage to soften severity.
  • KEV as of disclosure day — CISA doesn't list on speculation. Active exploitation overrides EPSS's low 0.00836 score, which lags by weeks.
  • Role multiplier — web-facing CMS component: the chain succeeds on the canonical deployment (public Joomla site with a contact/lead form). Blast radius: full site compromise → DB creds → potential lateral movement on shared hosting or reused admin creds → SEO poisoning, skimming, or foothold for further internal pivot.
  • Compensating deployment hardening is rare — Joomla installs do not ship with PHP execution disabled in upload directories by default; SELinux/AppArmor is not the norm on shared LAMP hosting.
  • Patch and mitigation are both cheap — 2.4.1 is a drop-in extension update. There is no operational reason to delay.

Why not higher?

9.8 is already at the CRITICAL ceiling for CVSS 3.1 in this configuration; the only headroom would be a Scope-changed variant, which is not applicable to a userland PHP webshell. There is no separate 'CRITICAL+' bucket in noisgate.

Why not lower?

Downgrading would require either evidence that the exposed population is trivial (it is not — Balbooa Forms is a mainstream Joomla forms extension) or evidence that exploitation requires a rare prerequisite (it does not — anonymous single-request). Neither condition holds.

06 · Verification

Crowdsourced verification payload.

Run on each Joomla host as any user that can read the webroot. Invoke as ./check-baforms.sh /var/www/html (path to Joomla document root). Also runs a live HTTP probe against the site — provide site URL as SITE_URL=https://example.com ./check-baforms.sh /var/www/html. Prints VULNERABLE, PATCHED, or UNKNOWN and exits with 1/0/2 respectively.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# noisgate: CVE-2026-56291 — Balbooa Forms unauth file upload
# Usage: ./check-baforms.sh <joomla-webroot>
# Optional: SITE_URL=https://site.tld ./check-baforms.sh <webroot>
set -u

ROOT="${1:-}"
if [[ -z "$ROOT" || ! -d "$ROOT" ]]; then
  echo "UNKNOWN: pass Joomla webroot as arg 1" >&2
  exit 2
fi

MANIFEST="$ROOT/administrator/components/com_baforms/baforms.xml"
ALT="$(find "$ROOT" -type f -name 'baforms.xml' 2>/dev/null | head -n1 || true)"
[[ -f "$MANIFEST" ]] || MANIFEST="$ALT"

if [[ -z "$MANIFEST" || ! -f "$MANIFEST" ]]; then
  echo "UNKNOWN: Balbooa Forms not found under $ROOT"
  exit 2
fi

VER=$(grep -oE '<version>[^<]+' "$MANIFEST" | head -n1 | sed 's/<version>//')
if [[ -z "$VER" ]]; then
  echo "UNKNOWN: could not parse version from $MANIFEST"
  exit 2
fi

FIXED="2.4.1"
# semver compare: is $VER < $FIXED?
lt() { [ "$1" = "$2" ] && return 1; [ "$(printf '%s\n%s\n' "$1" "$2" | sort -V | head -n1)" = "$1" ]; }

if lt "$VER" "$FIXED"; then
  STATUS="VULNERABLE"
  RC=1
else
  STATUS="PATCHED"
  RC=0
fi

echo "Balbooa Forms version: $VER  (fixed: $FIXED)"
echo "Manifest: $MANIFEST"
echo "Status: $STATUS"

# Optional live probe for stray webshells in common Balbooa upload dirs
for d in "$ROOT/images/baforms" "$ROOT/media/com_baforms/uploads" "$ROOT/images/com_baforms"; do
  if [[ -d "$d" ]]; then
    HITS=$(find "$d" -type f \( -iname '*.php*' -o -iname '*.phtml' -o -iname '*.phar' -o -iname '*.pht' -o -iname '*.inc' \) 2>/dev/null)
    if [[ -n "$HITS" ]]; then
      echo "WARNING: executable files present in upload dir $d:"
      echo "$HITS"
      RC=1
    fi
  fi
done

exit $RC