Suite de scripting servers: Webmin, Usermin, accel-ppp y CUPS
Cuatro sinks de inyección de comandos en una misma familia de scripting servers (Webmin y Usermin comparten el motor miniserv), más el túnel L2TP de accel-ppp y la cadena cups-browsed→foomaticrip de CUPS. Incluye el análisis del bypass de confianza X-SSL-Client-* y su alcance real.
/suite_scripting_servers +
00. Resumen de los Cuatro Sinks
| Target | Sink | Clase | Privilegio | Alcance |
|---|---|---|---|---|
| Webmin | cpan/install.cgi:45 | CWE-78 | root | Post-auth |
| Usermin | ssh/setup.cgi:9/12 | CWE-78 | no-root | Post-auth |
| accel-ppp | ip-up/down ($6) | CWE-78 | root | L2TP (config) |
| CUPS | foomaticrip sh -c | CWE-78 | lp | LAN |
El hilo común es que todos ejecutan un shell con datos que en algún punto provienen de la red o de un campo de configuración sin sanear. Son la clase de bug que el core de cada producto ha ido endureciendo, pero que sobrevive en los scripts admin y los helpers —lo que esta serie llama la superficie que el mantenimiento no mira.
01. 0x00 — Webmin cpan/install.cgi
El módulo de instalación de módulos Perl de Webmin (CPAN) pasa los argumentos del usuario directamente a la apertura de un pipe de comandos:
El sink está en el cierre del pipe con |, que el intérprete ejecuta con /bin/sh -c. Un módulo como ;touch /tmp/x;# termina la parte "normal" y ejecuta el comando inyectado. El alcance es post-auth: requiere una sesión válida de Webmin (con los privilegios del administrador, root). No es un bug pre-auth.
02. 0x01 — Usermin ssh/setup.cgi y find.cgi
Usermin comparte el motor miniserv con Webmin pero sirve a usuarios normales, no al admin. Tiene dos sinks de la familia:
Ambos son post-auth y, por defecto, corren con el uid del usuario de Usermin (miniserv baja el euid): el RCE llega como un usuario no-root. La inyección es real pero el impacto queda acotado a la cuenta del usuario autenticado salvo que la configuración eleve privilegios.
03. 0x02 — accel-ppp L2TP → scripts ip-up
accel-ppp es un servidor PPP/BGP/L2TP para BRAS y LNS de ISP. En su modo de compatibilidad pppd_compat, ejecuta los scripts ip-up/ip-down con los campos de la sesión sin escapar. El AVP que llega sin sanear es el CALLING_SID (el identificador llamante), que se expande en el script:
Es un camino pre-auth y 0-click por UDP L2TP (puerto 1701), porque el túnel se inicia antes de autenticarse. La ejecución es root (los scripts de ppp corren como root). La limitación real es que requiere la config de compatibilidad pppd_compat con los scripts presentes, que no es la instalación por defecto pura.
04. 0x03 — CUPSF: cups-browsed → foomaticrip
CUPS es el sistema de impresión estándar. El daemon cups-browsed descubre impresoras de red y, al procesar trabajos, deriva el filtro foomaticrip que ejecuta con un shell:
El vector es el descubrimiento de impresoras de red (cups-browsed): un perfil fuera del allowlist del mantenedor se interpola en el comando del filtro. Ejecuta como lp (usuario del sistema de impresión). El alcance es una LAN con impresión en red (cups-browsed activo), no Internet de forma directa.
05. 0x04 — El bypass de confianza X-SSL-Client-*
Webmin/Usermin validan la autenticación por cliente SSL. En despliegues detrás de un reverse proxy, el motor miniserv confía en las cabeceras X-SSL-Client-* que el proxy inyecta para indicar el certificado del cliente:
La clase de riesgo conceptual es que, si el motor no distingue una cabecera inyectada por el atacante de una inyectada por el proxy, todos los sinks post-auth de la familia podrían volverse pre-auth por composición. Tras validación rigurosa, el alcance real de este bypass en config estándar es limitado:
- Requiere trust_real_ip=1 en miniserv.conf (opt-in del admin para reverse proxy).
- El peer IP del cliente debe estar dentro de trusted_proxies; si no, el motor borra esas cabeceras (delete $header{...}).
- El X-SSL-Client-DN espoofeado debe coincidir exacto con un certificado pre-registrado a un usuario en find_user_by_cert. No es un bypass ciego fabricable a voluntad.
Con los tres prerequisitos activos, el bypass sí convierte los sinks post-auth en pre-auth. Pero ninguna de esas condiciones es el valor por defecto de la configuración: son cambios que un admin habilita para operar tras un reverse proxy. La lección general de este análisis es verificar siempre el valor real de la configuración por defecto antes de declarar una clase de alcance; "común en producción" no es lo mismo que "config por defecto".
06. 0x05 — Referencias
| Referencia | Descripción |
|---|---|
| Webmin cpan/install.cgi:45 | Sink open(CMD,"...|") → sh -c, heredado/multi-año |
| Usermin ssh/setup.cgi:9/12 | system() con $type sin quotemeta |
| Usermin htaccess/find.cgi:9 | open(FIND,"...|") con input del request |
| accel-ppp ip-up/down | eval de CALLING_SID ($6) sobre AVP L2TP |
| CUPSF cups-browsed | cupsICCProfile → foomaticrip sh -c (variante CVE-2024-47177) |
| miniserv-lib.pl | Confianza en cabeceras X-SSL-Client-* (bypass condicional) |
| CWE-78 | Improper Neutralization in OS Command |
Estos sinks se publican con fines de hardening y concienciación. La mitigación común a toda la familia es simple y robusta: nunca interpolar datos de red o de request en un shell — usar quotemeta/escapado en Perl para la familia miniserv, no derivar comandos por eval en los scripts ppp, y validar los perfiles contra el allowlist en CUPS. Cada caso fue comunicado al mantenedor como parte del proceso responsable.