2023/07/04

Reflexiones sobre rbash

Supongamos que tenemos un linux al cual se accede por ssh. La situación normal es que a nivel de permisos tenemos root y el resto.

El usuario root puede hacer todo, listo.

Dentro de ese resto, manejando grupos y permisos podríamos más o menos manejar algún tipo de restricción. Una medida común es utilizar sudo, que habilita  una lista de acciones que podrá ejecutar quien tenga los permisos.

Pero, ponele que en lugar de estar viendo como le permitimos a los usuarios hacer algunas tareas administrativas, estamos buscando restringir lo que ya pueden hacer. Si el usuario en realidad es una cuenta para que un script pueda ejecutar algunas consultas sobre el sistema, no hay motivo para que pueda ejecutar ningún otro comando que no corresponda a lo que va a hacer.

Para este requerimiento, se puede usar rbash.

Si, si, ahí los del fondo, escuché que existe selinux y apparmor, pero esas son palabras mayores, quedémonos con lo sencillo.


Lo que hace rbash es empezar por desabilitar un montón de comportamiento provisto por bash, acá está la lista completa, lo más importante es que no permite cd ni cambiar la ruta de invocación de comandos.

Además:

The restricted shell mode is only one component of a useful restricted environment. It should be accompanied by setting PATH to a value that allows execution of only a few verified commands (commands that allow shell escapes are particularly vulnerable), changing the current directory to a non-writable directory other than $HOME after login, not allowing the restricted shell to execute shell scripts, and cleaning the environment of variables that cause some commands to modify their behavior (e.g., VISUAL or PAGER). 


Sumado a eso, en .bashrc o similar hay que setear el PATH a una carpeta con symlinks a los ejecutables permitidos, según he visto que se hace.


Luego, se debe considerar que:

When a command that is found to be a shell script is executed (see Shell Scripts), rbash turns off any restrictions in the shell spawned to execute the script.

Estoy citando pues como tengo casi nula experiencia con rbash, me siento irresponsable. Pero mi ínfima experiencia algo me ha hecho pensar.

 

Vamos ahora al escenario concreto, quiero:

  • que exista una cuenta
  • que tenga shell restringido
  • a la que sólo se pueda acceder vía ssh
    • esto implica no login por consola ni "desplazamiento lateral" tipo su o login

Este comando lo hace:

$ sudo adduser  --shell /usr/bin/rbash --disabled-login  prueba

Si estás modificando un usuario existente, editás /etc/password para que tenga el shell correcto y /etc/password para deshabilitar el login.

También se hace con 

$ sudo passwd -l prueba

Que le agrega a "!" al password existente.

De un modo u otro lo controlás con:

$ sudo grep prueba /etc/passwd /etc/shadow
/etc/passwd:prueba:x:1001:1001:,,,:/home/prueba:/usr/bin/rbash
/etc/shadow:prueba:!:19542:0:99999:7:::

Solo vía ssh, hay que habilitar la key ya que se trata de clientes script, no de personas ingresando claves, aunque con la key un usuario puede entrar.

$ ssh-keygen -f prueba.key -t ecdsa

En la carpeta del usuario prueba, hay que crear .ssh con rwx------ y el archivo authorized_keys con permisos rw------- y el contenido de prueba.key.pub.

 

rbash en acción
rbash en acción

El problema que hay acá es que si ejecutás:

$ ssh prueba@localhost -t bash

sshd ignora el shell de /etc/passwd y te da un shell irrestricto.

 

rbash bypass
rbash bypass

Se arregla de dos maneras, una global y otra específica para cada usuario.


La global es poner en sshd_config esta línea, que no la probé:

ForceCommand rbash

Tiene la ventaja de restringir a todos por si alguno se te escapa, pero si querías tener uno que haga de administrador, vas a tener que ponerle específicamente que pueda ejecutar sudo.
 
La específica para cada usuario es poner no-pty  en  .ssh/authorized_keys
a la key con la que se autentica.Queda algo asi:


no-pty ssh-ed25519 AAAAC3NzaC1....

El problema es que perdés el prompt y bash completion, algo completamente irrelevante para un script.

 
rbash con no-tty en authorized_keys
rbash con no-tty en authorized_keys

 

no login
no login

Mis reflexiones

 

Porque no password al azar

Se podría poner un password al azar, pero al ser un password existente hay una increíblemente remota posibilidad de que alguien le acierte. También que al azar sea un password en un diccionario. O que en el momento de la creación haya leak.

Es mejor poner "!" antes que usar azar pues es un indicador visual y fácil de controlar de modo automático que luego no cambie la situación.

Es mejor dejar solo "!" pues agrega que no haya ninguna posibilidad de login.


Porque no ForceCommand rbash

Si la idea es que en ese equipo no haya ningún usuario remoto sin rbash, de acuerdo con ForceCommand rbash. Pero eso implica que al menos a algún usuario hay que habilitarle que pueda ejecutar sudo, además de las reglas de sudoers.

Me parece más sencillo configurar no-pty en .ssh/authorized_keys para cada usuario a restringir.

Igual en este aspecto mi opinión no es tan fuerte como con el punto anterior. De hecho, mientras escribo esto, no puedo dejar de notar que ForceCommand rbash + sudo responde más a la política de denegar todo y luego permitir de a uno, como que cambiaría de idea muy fácil... listo, ya cambié de idea.

Igual mi instinto algo me dice a favor de no-pty, por el lado de evitar una denegación de servicio. Si vuelvo a cambiar de idea, lo registraré.

Mi posición actual es, depende del perfil de uso del equipo, si es de uso general y hay que restringir a un usuario de servicio, no-pty, si nadie debería acceder salvo ciertas tareas de mantenimiento, ForceCommand rbash + sudo.

 

Disclaimer

No tomes este post como ninguna autoridad de cómo implementar correctamente rbash, no he investigado la parte de las variables de entorno ni sometido a pruebas exhaustivas.

 

 

No hay comentarios:

Publicar un comentario