Dropbear: un rodeo de las restricciones SSH alcanza sockets de root
Una clave de Dropbear limitada a un destino TCP puede abrir sockets Unix, incluido docker.sock, porque las comprobaciones omiten el reenvío de flujos.
Resumen
- Dropbear aplica
permitopenypermitlistenal reenvío TCP, pero no al reenvío de sockets Unix. Una clave restringida a un destino TCP puede abrir cualquier socket al que llegue la cuenta. - Todas las versiones de Dropbear hasta 2026.94 y el HEAD de Git
99baf182están afectadas. Las opciones de reenvío de flujos local y remoto están activadas por defecto. - El investigador knell la puntúa 9.9 cuando la cuenta puede llegar al demonio Docker o a un socket de base de datos. No hay CVE asignado, no se ha notificado explotación y no está en el catálogo KEV de CISA a fecha del 14 de noviembre de 2026.
- No existe una versión corregida. Añada
no-port-forwardinga las claves restringidas, o recompile Dropbear con las opciones de reenvío de flujos desactivadas. Consulte "¿Cómo lo corrijo?" para el coste de cada opción.
¿Estoy afectado?
Está expuesto cuando se cumplen todas estas condiciones:
- El servidor ejecuta Dropbear, cualquier versión o el HEAD de Git hasta
99baf182(2026-11-11). - La compilación mantiene activado el reenvío de sockets Unix.
DROPBEAR_SVR_LOCALSTREAMFWDyDROPBEAR_SVR_REMOTESTREAMFWDvalen 1 por defecto. - Al menos una entrada de
authorized_keysllevapermitopen=opermitlisten=. La restricción es la razón por la que el titular de la clave no tiene acceso general. - La cuenta de esa clave puede llegar a un socket Unix sensible, como
/var/run/docker.socko un socket de base de datos. El caso 9.9 del investigador es el socket Docker. - El atacante tiene esa clave restringida, o puede usar la cuenta que la tiene.
Una clave sin restricción permitopen o permitlisten no es el objeto de este fallo: su titular ya tiene acceso general de reenvío. El rodeo importa para las claves que un administrador restringió deliberadamente.
| Rama | Versiones afectadas | Versión corregida |
|---|---|---|
| Versiones publicadas | Hasta 2026.94 (2026-07-23) | Ninguna |
| Git | Hasta 99baf182 (2026-11-11) |
Ninguna |
Compruebe la versión del servidor y las claves restringidas:
# Server and client version
dropbear -V
# Keys that carry a per-destination restriction
grep -R -E 'permitopen=|permitlisten=' /home/*/.ssh/authorized_keys /root/.ssh/authorized_keys 2>/dev/null
# Accounts that can reach the Docker socket
getent group docker
La lista de claves es la comprobación importante. Una clave permitopen cuya cuenta también está en el grupo docker es el caso 9.9 que describe el investigador.
¿Cómo lo corrijo?
No existe una versión corregida de Dropbear a fecha del 14 de noviembre de 2026. Aplique una de estas tres mitigaciones, por orden de preferencia, y retírela cuando el proyecto publique una corrección basada en la ruta.
- Añada
no-port-forwardinga cada clave que llevepermitopenopermitlisten. Los manejadores de reenvío de flujos comprueban ese indicador mediantesvr_pubkey_allows_tcpfwd(), así que la clave ya no puede abrir sockets Unix. El coste es que la clave pierde también todo el reenvío TCP, incluido el destino que el administrador permitió. - Recompile Dropbear con
DROPBEAR_SVR_LOCALSTREAMFWD 0yDROPBEAR_SVR_REMOTESTREAMFWD 0enlocaloptions.h. El coste es que ninguna cuenta de ese servidor puede usar el reenvío de sockets Unix. - Inicie el servidor con
-j -k. Esos indicadores activannolocaltcpynoremotefwd, que los manejadores de reenvío de flujos comprueban. El coste es que todas las cuentas pierden el reenvío local y remoto, no solo las claves restringidas.
Quitar la cuenta del grupo docker y endurecer los permisos de los sockets reduce el impacto. No cierra el rodeo: la clave todavía puede llegar a cualquier otro socket que la cuenta pueda abrir, incluidos los de bases de datos y servicios.
El investigador recomienda un equivalente de permitopen basado en la ruta, aplicado en svr-streamfwd.c con el mismo recorrido de lista que usa la ruta TCP. Vigile la página de versiones de Dropbear para ese cambio; el proyecto no ha publicado una versión corregida.
¿Cuál es la causa raíz?
Los manejadores de reenvío de sockets Unix solo comprueban el indicador general no-port-forwarding. Nunca llaman a las funciones que recorren la lista de destinos de la clave.
Dropbear guarda las restricciones en authorized_keys. svr_pubkey_allows_tcpfwd() en la línea 65 de src/svr-authpubkeyoptions.c devuelve 0 solo cuando la clave lleva no-port-forwarding:
int svr_pubkey_allows_tcpfwd() {
if (ses.authstate.pubkey_options
&& ses.authstate.pubkey_options->no_port_forwarding_flag) {
return 0;
}
return 1;
}
Las comprobaciones por destino están en svr_pubkey_allows_local_tcpfwd() y svr_pubkey_allows_remote_tcpfwd() en el mismo archivo. src/svr-tcpfwd.c las llama en las líneas 202 y 99. Los dos manejadores de reenvío de flujos no lo hacen.
En src/svr-streamfwd.c, el manejador local newstreamlocal() comprueba svr_opts.nolocaltcp y svr_pubkey_allows_tcpfwd() en la línea 294. El manejador remoto svr_remotestreamlocalreq() comprueba svr_opts.noremotefwd y la misma función en la línea 219. Una búsqueda en el árbol encuentra las dos funciones por destino referenciadas solo desde src/svr-tcpfwd.c.
La compilación por defecto activa las dos opciones de reenvío de flujos en las líneas 76 y 77 de src/default_options.h. El canal se registra en src/svr-session.c.
La corrección incompleta es visible en el historial. El commit 796a89ef (2024-04-03), "Apply tcp forwarding restrictions to unix sockets too", añade la comprobación general a newstreamlocal() y actualiza el manual. No añade la comprobación por destino que anuncia su título.
El autor señala en las líneas 213 y 214 de src/svr-streamfwd.c que la comprobación podría relajarse si existiera un equivalente de permitlisten para streamlocal. Ese equivalente no existe.
¿Cómo se explota?
- El atacante se autentica con una clave que el administrador restringió a un destino TCP con
permitopen="host:port". - El atacante abre un canal
direct-streamlocal@openssh.comhacia una ruta de socket Unix en lugar de un destino TCP. - El manejador de reenvío de flujos de Dropbear comprueba el indicador
no-port-forwardingy el interruptor general de reenvío. Ambos pasan, porque la clave no llevano-port-forwarding. - El manejador nunca consulta la lista
permitopen, así que se conecta al socket solicitado. - El atacante habla el protocolo del socket. En
/var/run/docker.sock, la API de Docker puede iniciar un contenedor con el sistema de archivos del host montado, lo que equivale a root en el host.
El investigador demostró el rodeo en un banco local construido con el código fuente fijado. Una clave con permitopen="127.0.0.1:1" fue rechazada cuando pedía 127.0.0.1:22, pero la misma clave alcanzó /tmp/target.sock. Después abrió /var/run/docker.sock y recibió HTTP/1.1 200 OK, Api-Version 1.56 del demonio real.
La dirección remota funciona igual. Una clave con permitlisten puede hacer que el servidor escuche en una ruta Unix escribible arbitraria y suplantar un socket de servicio.
¿Cómo se desarrolla el ataque?
Una clave restringida pasa la comprobación general de reenvío, pide un socket Unix en lugar de un destino TCP y alcanza un socket que el administrador nunca autorizó.
permitopen a un host TCP"] --> B["Se conecta a Dropbear
con esa clave"] B --> C["Abre un canal direct-streamlocal
hacia docker.sock"] C --> D["El manejador solo comprueba
no-port-forwarding"] D --> E["La lista permitopen
nunca se consulta"] E --> F["Dropbear se conecta al
socket propiedad de root"] F --> G["La API de Docker ejecuta un contenedor
con el sistema de archivos del host"]
¿Qué puede hacer un atacante?
El atacante alcanza los sockets Unix que la cuenta puede abrir, aunque la clave estaba restringida a un destino TCP. Cuando la cuenta llega al socket Docker, eso equivale a root en el host.
El impacto depende de los sockets que la identidad del sistema operativo de la cuenta puede tocar:
/var/run/docker.sockpermite al atacante ejecutar un contenedor con el sistema de archivos del host montado como root. El investigador lo describe como equivalente a root en el host.- Los sockets de bases de datos como
/run/mysqld/mysqld.socky/run/postgresql/.s.PGSQL.5432exponen la base al titular de la clave. - Los sockets de agentes y servicios exponen lo que esos servicios aceptan.
- En la dirección
permitlisten, el atacante puede hacer que el servidor escuche en una ruta escribible arbitraria y suplantar un socket de servicio.
Las condiciones forman parte del impacto: el atacante necesita una clave restringida válida. La cuenta debe poder abrir el socket objetivo, y la compilación debe mantener el reenvío de flujos activado. El investigador puntúa el caso Docker CVSS v3.1 9.9 con AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H, y alrededor de 7 cuando solo son alcanzables los sockets de la cuenta.
No es un fallo no autenticado. El atacante tiene una clave que el administrador emitió, y el administrador la restringió precisamente para limitar lo que esa clave puede hacer.
¿Por qué funciona la corrección?
Todavía no existe una corrección upstream. El cambio que cierra el rodeo aplica a los dos manejadores de reenvío de flujos el mismo recorrido de lista por destino que ya usan los manejadores TCP.
La comprobación que falta es visible en los dos manejadores. El manejador local en la línea 294 de src/svr-streamfwd.c dice ahora:
if (svr_opts.nolocaltcp || !svr_pubkey_allows_tcpfwd()) {
Una comprobación completa llamaría también a un equivalente basado en la ruta de svr_pubkey_allows_local_tcpfwd() para la ruta de socket solicitada. Rechazaría el canal cuando la clave lleva una lista de destinos que no la incluye. El manejador remoto en la línea 219 necesita el mismo cambio para permitlisten.
La recomendación del investigador es rechazar directamente los canales streamlocal para cualquier clave que lleve una restricción por destino. La regla se mantiene hasta que exista una opción basada en la ruta. Es la corrección conservadora y es fácil de razonar: una clave que nombra destinos no obtiene sockets Unix.
La mitigación no-port-forwarding funciona porque activa el indicador que lee la comprobación general existente. Las mitigaciones de compilación y -j -k funcionan porque activan los interruptores generales que leen los manejadores. Ninguna es una corrección de código del recorrido de lista que falta.
¿Cómo compruebo si estuve comprometido?
No se ha notificado explotación y no se han publicado indicadores de compromiso. Las comprobaciones buscan las condiciones y el uso de los sockets, no una carga útil conocida.
- Enumere cada clave que lleva
permitopenopermitlisten, y la cuenta que la posee. - Compruebe si esas cuentas están en el grupo
dockero pueden abrir sockets de bases de datos. - Revise los registros de auditoría del demonio Docker para llamadas a la API desde procesos o usuarios locales inesperados, sobre todo creaciones de contenedores con montajes del host.
- Revise los registros de las bases de datos para conexiones por socket local desde usuarios del sistema que no se conectan normalmente.
- Busque contenedores, imágenes o montajes que nadie del equipo haya creado.
El registro predeterminado de Dropbear es mínimo, y el análisis no publica ninguna firma de registro. Un intento fallido puede no dejar rastro, y uno exitoso deja sus efectos en el servicio al que pertenece el socket.
Cronología
- 2024-04-03: el commit
796a89efaplica la restricción general de reenvío TCP a los sockets Unix, pero no las comprobaciones por destino. - 2025-12-09: el commit
00cfa132bloquea el reenvío de flujos Unix para claves con comando forzado, una restricción distinta en la misma ruta. - 2026-07-23: Dropbear publica 2026.94.
- 2026-11-11: el investigador prueba el HEAD de Git
99baf182; el rodeo está presente. - 2026-11-13: el investigador publica el análisis y la prueba en directo en la lista oss-security.
Preguntas frecuentes
¿Existe un CVE para este fallo?
No. El investigador publicó el análisis en la lista oss-security el 13 de noviembre de 2026, y no existe ningún registro CVE a fecha del 14 de noviembre. El proyecto Dropbear no ha publicado un aviso.
¿permitopen protege los sockets Unix?
No. permitopen y permitlisten solo se aplican en las rutas de reenvío TCP. Los manejadores de sockets Unix comprueban el indicador no-port-forwarding y el interruptor general de reenvío, no la lista de destinos.
¿Es un fallo remoto y no autenticado?
No. El atacante necesita una clave válida que el administrador restringió con permitopen o permitlisten. La gravedad depende de lo que pueda alcanzar la cuenta de esa clave.
¿Qué versiones están afectadas?
Todas las versiones de Dropbear hasta 2026.94 y el HEAD de Git hasta 99baf182 (2026-11-11). No hay una versión corregida a fecha del 14 de noviembre de 2026.
¿no-port-forwarding bloquea el rodeo?
Sí. no-port-forwarding activa el indicador que lee svr_pubkey_allows_tcpfwd(), así que los dos manejadores de reenvío de flujos rechazan el canal. También bloquea todo el reenvío TCP de esa clave, incluido el destino permitido.
¿Y si la cuenta no está en el grupo docker?
El atacante puede alcanzar igualmente cualquier socket que la cuenta pueda abrir, como un socket de base de datos o de servicio. El impacto es menor que root en el host, pero sigue siendo un acceso que la restricción de la clave debía impedir.
Referencias
- knell, "Dropbear: the restriction names an address", oss-security, 13 de noviembre de 2026, el análisis y la prueba en directo: https://www.openwall.com/lists/oss-security/2026/11/13/4 (consultado el 14 de noviembre de 2026)
- El artículo del investigador, "Not an address", el análisis completo y el banco de pruebas: https://archive.org/details/knell-not-an-address (consultado el 14 de noviembre de 2026)
- Código fuente de Dropbear en
99baf182,src/svr-streamfwd.c, los dos manejadores de reenvío de flujos: https://github.com/mkj/dropbear/blob/99baf1828c13e88de048e641d03694bfe8923251/src/svr-streamfwd.c (consultado el 14 de noviembre de 2026) - Código fuente de Dropbear en
99baf182,src/svr-authpubkeyoptions.c, la comprobación general y las comprobaciones por destino: https://github.com/mkj/dropbear/blob/99baf1828c13e88de048e641d03694bfe8923251/src/svr-authpubkeyoptions.c (consultado el 14 de noviembre de 2026) - Código fuente de Dropbear en
99baf182,src/default_options.hlíneas 76 y 77, los valores predeterminados del reenvío de flujos: https://github.com/mkj/dropbear/blob/99baf1828c13e88de048e641d03694bfe8923251/src/default_options.h (consultado el 14 de noviembre de 2026) - Commit
796a89ef, "Apply tcp forwarding restrictions to unix sockets too", 3 de abril de 2024: https://github.com/mkj/dropbear/commit/796a89efd21f (consultado el 14 de noviembre de 2026) - Commit
00cfa132, "Disallow unix stream forwarding for forced command", 9 de diciembre de 2025: https://github.com/mkj/dropbear/commit/00cfa132fcbf (consultado el 14 de noviembre de 2026) - Página del proyecto Dropbear, el caso de uso embebido y de router y la versión 2026.94: https://matt.ucc.asn.au/dropbear/dropbear.html (consultado el 14 de noviembre de 2026)
- Catálogo Known Exploited Vulnerabilities de CISA, consultado para una entrada de Dropbear el 14 de noviembre de 2026 (ninguna): https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json (consultado el 14 de noviembre de 2026)