En el puerto 8787 nos encontramos con el servicio drb (Distributed Ruby), este es un sistema de comunicación remota que permite a múltiples programas escritos en Ruby interactuar entre sí a través de la red, como si estuvieran corriendo en la misma máquina. Permite la llamada a métodos remotos (RMI - Remote Method Invocation).

Explotación

El gran problema de DRb es que no requiere contraseñas, tokens ni certificados para conectarse. Un atacante puede conectarse a este puerto y enviar un objeto de ruby serializado malicioso. Cuando el servidor recibe este objeto y lo reconstruye (deserializa), ejecuta el código que lleva dentro de forma automática. El resultado es la ejecución remota de código (RCE) instantánea con los privilegios del servicio que lo levantó, por lo general root.

El objeto remoto del servidor nos está respondiendo directamente con un arreglo de símbolos que representan los métodos que tiene cargado en la memoria. Este resultado es la fuga de información técnica y nos muestra las “llaves” del reino…

method_missing: Este método es un comodín en Ruby. Si intentamos llamar a un método que supuestamente no existe en el objeto remoto, en lugar de lanzar un error y cerrar la conexión, el flujo car en :method_missing. Un atacante puede usar eso para enviar payloads personalizados que fuercen al servidor a buscar otras librerías del sistema y ejecutarlas.

:instance_eval y instance_exec: Estos métodos permiten evaluar strings como si fueran código de Ruby vivo dentro del contexto del objeto. Si le pasamos un string con comandos del sistema (como un system('whoami'), el servidor lo procesará y lo ejecutará localmente

:public_send y :send: Permiten invocar de forma dinámica cualquier otro método interno de las clases de Ruby instaladas en la víctima, saltándose las restricciones de visibilidad estándar del código.

Hardening

El riesgo es alto teniendo este servicio expuesto (el cuál no debería estar abierto en ningún entorno de producción real), la recomendación prioritaria es dehabilitar el servicio por completo o restringir su visibilidad a nivel de red.

Si por alguna razón de negocio el servicio debiera seguir ejecutándose pero de manera aislada, podemos configurar reglas de firewall para denegar cualquier conexión entrante que no provenga de la propia máquina.

iptables -A INPUT -p tcp --dport 8787 ! -s 127.0.0.1 -j DROP

Los paquetes ahora son bloqueados o ignorados antes de ser procesados. El atacante no recibirá ninguna respuesta, no sabe si el puerto está ocultando algo o si hay algún firewall en el medio.