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

The Joomla extension Balbooa Forms is vulnerable to an unauthenticated arbitrary file upload

ASSESSED — NOISGATE V0.5
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 · 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 CRITICALno 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
04 · The Call

noisgate verdict.

Final Verdict
= UNCHANGED to CRITICAL (9.8/10)

Unauthenticated single-request RCE against an internet-facing PHP application, with active in-the-wild exploitation confirmed by CISA KEV listing on the day of disclosure. There is no friction step in the chain that meaningfully narrows the exposed population — the decisive factor is the combination of AV:N/PR:N/UI:N reachability with confirmed mass exploitation.

HIGH exploitation is real and ongoing
HIGH affected/fixed version boundaries
MEDIUM exact installed-base count on public internet

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.

05 · Compensating Control

What to do — in priority order.

  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.
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
07 · Bottom Line

If you remember one thing.

TL;DR
This is a KEV-listed, unauthenticated, single-request RCE with public PoC and pre-patch exploitation — treat it as an incident-response event, not a patch ticket. Because it is KEV, the noisgate mitigation SLA is overridden to patch or mitigate within hours today: either upgrade Balbooa Forms to 2.4.1 or disable the component and deploy the WAF virtual patch before end-of-day 2026-07-13. Under the noisgate remediation SLA for CRITICAL, the full 2.4.1 rollout across all Joomla hosts is due within 90 days, but for anything internet-facing you should be done within a week and running compromise-assessment sweeps (webshell hunt, #__users review, configuration.php secret rotation) in parallel. Assume public sites were probed before you patched.

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
Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously
Validation Results

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.