Ventiladores al máximo en el salón y un minero oculto en segundo plano
En la esquina de un salón silencioso, los ventiladores de un centro multimedia doméstico comenzaron a girar de repente a máxima potencia durante toda la noche. El equipo se utilizaba habitualmente solo para reproducir películas en 4K y su carga de trabajo solía ser insignificante. Al acceder al panel de administración, el propietario descubrió que el uso de la CPU llevaba varios días clavado en el 100%.
Dos procesos desconocidos consumían potencia de cálculo sin descanso: uno camuflado como un proxy de red con el nombre myawesomeproxy y otro dedicado a la minería de criptomonedas llamado mylovelyminer. El usuario no había descargado ningún paquete de origen desconocido y el panel de control estaba protegido con una contraseña exclusiva y robusta.
El origen del problema residía en Plex Media Server. Varios investigadores de seguridad hicieron pública una cadena de ejecución remota de código denominada plex2shell (CVE-2026-96652, -96654, -96655, -96656), que afecta a las versiones 1.43.2 e inferiores. Cualquier atacante desde internet, sin necesidad de credenciales, podía tomar el control absoluto del servidor mediante una secuencia de peticiones manipuladas.
Figura: Registro en honeypot que muestra la descarga automatizada de cargas maliciosas por parte de los atacantes. Fuente: BoredHackerBlog.
Engañar al servidor para que se ataque a sí mismo mediante devoluciones de llamada sin validar
Muchos servicios de red interna asumen una premisa cómoda: cualquier petición procedente de localhost es intrínsecamente segura. Para ahorrar la sobrecarga de verificar cada comunicación interna, Plex relajó sustancialmente las reglas de inspección para el tráfico en bucle local. Ese modelo de confianza ciega se convirtió en la brecha que desmoronó la seguridad. Bastaba con engañar al servidor para que dirigiera peticiones contra sí mismo.
La primera grieta apareció en la interfaz de línea de tiempo del reproductor, /player/timeline, empleada para notificar el progreso de reproducción. Por diseño requería el encabezado X-Plex-Token, pero el código del servidor se limitaba a llamar al método hasParam(). Este método solo comprueba la existencia del encabezado sin validar su contenido ni autenticidad; cualquier cadena aleatoria bastaba para franquear la entrada.
Una vez superado este filtro, el servidor envía notificaciones de suscripción a eventos a la dirección del reproductor. El código construía el enlace de retorno mediante boost::format("%1%://%2%:%3%"). El parámetro de protocolo protocol carecía por completo de validación de formato o filtrado de caracteres.
El atacante introdujo una URL completa con una dirección de bucle local en ese parámetro. Plex emitió entonces una petición HTTP POST directa contra su propio puerto de administración interno. En la capa de transporte, la IP de origen pasó a ser 127.0.0.1, otorgando al atacante la condición de entidad local de confianza.
Un fallo en la comprobación de prefijos entrega el token de administrador
Disfrazado de petición local, el atacante accedió a la interfaz interna de gestión de complementos en /system/agents/*. Como la conexión procedía de la interfaz de bucle local, se omitió la autenticación. En el script agentservice.py, los desarrolladores habían definido una lista blanca dentro de la función searchOne.
Sin embargo, la función estaba envuelta por el decorador de bloqueo @lock. Este decorador no propagaba el valor de retorno de la función interna inner(). Cuando la comprobación de la lista blanca abortaba la ejecución para denegar el acceso, el decorador descartaba el resultado, dejando la protección completamente inutilizada.
Al mismo tiempo, el parámetro identifier carecía de saneamiento. La introducción de un signo de interrogación ? permitía inyectar parámetros de consulta, mientras que una almohadilla # truncaba la ruta predeterminada /messaging/.... Así quedó establecido el segundo eslabón.
El siguiente objetivo fue obtener privilegios globales de administrador. El marco de complementos de Plex contaba con una funcionalidad pensada para facilitar la integración: cualquier petición saliente hacia una dirección que comenzara por 127.0.0.1 recibía automáticamente los tokens de administración local-*. Pero el marco empleaba una simple coincidencia de prefijos de cadena sin verificar los límites del nombre de host. Una dirección como 127.0.0.1.evil.com superaba el filtro.
Mediante el servicio de DNS con comodín sslip.io, el atacante generó el dominio 127.0.0.1.10-0-0-9.sslip.io. Este nombre cumplía la regla del prefijo, pero al resolverse en los DNS públicos dirigía el tráfico directamente al servidor del atacante en 10.0.0.9. Plex validó la regla y envió de forma proactiva el token de administrador, activando el tercer fallo.
Figura: Registro en tiempo real obtenido por investigadores durante los escaneos y la explotación de vulnerabilidades desde direcciones IP maliciosas. Fuente: BoredHackerBlog.
Código malicioso oculto en píxeles de vídeo: abuso del transcodificador
Con el token de administrador en su poder, el atacante tenía capacidad para alterar los ajustes del servidor. Plex recurre a un transcodificador integrado para adaptar la imagen a diferentes dispositivos. El componente de codificación subyacente x264 disponía de opciones de depuración a las que el atacante inyectó sus propios argumentos: TranscoderH264Options=dump-yuv=<ruta>:qp=0.
La opción dump-yuv invoca internamente fopen(ruta, "w") y vuelca los fotogramas sin comprimir directamente en la ruta especificada. Al fijar el parámetro de cuantificación qp=0, se activa el modo sin pérdidas y los valores de los píxeles no sufren alteración. Con antelación, el atacante había compilado una biblioteca compartida en formato ELF (.so) que contenía únicamente un constructor de inicialización del sistema.
Los bytes de ese binario se insertaron uno a uno en el plano de luminancia (plano Y) del primer fotograma de un vídeo MP4. El resultado fue un archivo de vídeo H.264 aparentemente normal y completamente reproducible.
El atacante emitió entonces una petición de transcodificación autenticada con el token de administrador, apuntando el parámetro path a una lista de reproducción remota item.xml bajo su control. Plex descargó el vídeo portador y puso en marcha el transcodificador. En cuanto se descodificó el primer fotograma, se activó la función de depuración. La biblioteca maliciosa oculta en los píxeles fue escrita directamente por el propio motor de transcodificación en el directorio interno Codecs.
Ausencia de firmas digitales: una biblioteca sin nombre asume el control
Escribir el archivo malicioso en el disco era solo el paso intermedio; lograr que el sistema lo cargara era el objetivo final. El componente integrado libavutil.so.58 llama a la función avpriv_load_new_libs cada vez que se inicia el transcodificador. Esta función analiza el directorio Codecs y, si el nombre de un archivo termina en .so, ejecuta directamente dlopen(path, RTLD_NOW).
Este mecanismo de carga prescindía de comprobaciones de seguridad críticas: no exigía un prefijo estándar, no verificaba los permisos de ejecución del archivo y carecía de validación mediante firma digital. Incluso con permisos habituales de solo lectura, la biblioteca se cargaba directamente en la memoria del proceso.
De acuerdo con las especificaciones de las bibliotecas ELF, dlopen ejecuta automáticamente los constructores definidos en DT_INIT_ARRAY antes de resolver cualquier símbolo, sin necesidad de funciones exportadas. El constructor invocaba de inmediato fork() y execve(), abriendo una shell inversa con los privilegios del servicio bajo uid=1000(plex). La cadena quedaba completada.
Los modelos de lenguaje abaratan el descubrimiento de exploits en dispositivos de borde
La secuencia cronológica de este hallazgo fue muy ajustada. El investigador comunicó el problema el 27 de julio de 2026. El equipo de Plex confirmó el fallo y abonó la recompensa el 4 de agosto. El 23 de septiembre se asignaron cuatro identificadores CVE y el 16 de octubre se publicaron los parches y detalles técnicos.
Tras hacerse públicos los pormenores, aparecieron de inmediato ataques reales. Varios honeypots detectaron tráfico de sondeo automatizado desde las direcciones 45.194.92.222, 91.92.40.202 y 176.65.139.228. Los atacantes distribuían malware desde el servidor 217.60.194.116.
Entre las muestras interceptadas figuraba una imagen de contenedor con hash 5712ef510481f15fe8b18fdd10b73026d57cb3d9d151878a692358b99a464441 y un ejecutable comprimido con UPX identificado con 68938fb428f2bcfef4ede62f7b29cd0f15f37ed59e94462c099f2ca64e36baa7. Tras descomprimirlo, el binario principal presentaba el hash b20f39fc00d242e706b6c30367ad811c676e0575050a4ec2f30104b696944b49. Los atacantes aprovecharon que los servidores domésticos permanecen encendidos continuamente para desplegar proxys y minar criptomonedas en secreto.
La metodología empleada para descubrir la vulnerabilidad también ha suscitado gran interés. El investigador detalló el uso de un flujo de trabajo asistido por modelos de lenguaje (LLM), dividido en reconocimiento, triaje, verificación y encadenamiento, utilizando agentes independientes para refutar de forma sistemática cada hipótesis.
Los analistas humanos definieron las decisiones arquitectónicas y la estrategia de explotación, mientras las herramientas de IA redujeron el esfuerzo del análisis de código. El coste de enlazar pequeños defectos independientes para crear una cadena crítica ha caído en picado, dejando a los dispositivos de borde domésticos en la primera línea de fuego.
Esta cadena no dependía de complejas corrupciones de memoria. Un encabezado sin validar, una instrucción de bloqueo anulada por un decorador, una comprobación de prefijos descuidada y una carga indiscriminada de bibliotecas: cada punto era un descuido de desarrollo aislado.
La premisa de Plex de que el tráfico local siempre era de confianza unió estas deficiencias hasta convertirlas en una puerta trasera absoluta. La eliminación de controles por comodidad terminó siendo la vía más rápida para la pérdida total de control. Con escaneos automatizados ya activos en la red, actualizar a la versión 1.43.3 o posterior es fundamental para evitar que los servidores domésticos pasen a formar parte de granjas de minería ilícitas.
Enlaces de referencia:
- Informe de plex2shell en zmain.info
- Análisis de actividad real en BoredHackerBlog
- Repositorio GitHub code-zm/plex2shell
- Repositorio GitHub BoredHackerBlog/plex2shell_pcap
- Debate en Hacker News (item?id=50152321)