Saltar al contenido

¿Cómo crear un usuario SSH restringido para el reenvío de puertos?

Nuestro team especializado pasados muchos días de trabajo y de recopilar de información, encontramos los datos necesarios, queremos que resulte útil para ti para tu plan.

Solución:

TL; DR: vaya al final de la respuesta, “Aplicación de las restricciones”

Agregar un usuario restringido consta de dos partes: 1. Crear el usuario 2. Configurar el demonio SSH (sshd)

Configurando sshd

El mejor lugar para conocer las posibilidades de SSH es leyendo las páginas del manual relacionadas:

  • ssh (1)
  • ssh_config (5)
  • sshd (8)
  • sshd_config (5)

¿Dónde puede realizar acciones el cliente SSH?

Antes de poder restringir algo, necesita conocer las características de SSH. Escupir a través de las páginas del manual produce:

  • Ejecución de comandos de shell
  • Carga de archivos a través de sftp
  • Reenvío de puertos
    • El cliente reenvía un puerto (no) utilizado al servidor
    • El servidor reenvía su puerto al cliente.
    • El servidor reenvía un puerto de otro host al cliente (proxy-ish)
  • Reenvío X11 (reenvío de pantalla)
  • Reenvío del agente de autenticación
  • Reenvío de un dispositivo de túnel

Desde el Autenticación sección de la página del manual de sshd (8):

Si el cliente se autentica con éxito, se ingresa un diálogo para preparar la sesión. En este momento el cliente puede solicitar cosas como
asignar un pseudo-tty, reenviar conexiones X11, reenviar conexiones TCP o reenviar la conexión del agente de autenticación sobre el canal seguro.

Después de esto, el cliente solicita un shell o la ejecución de un comando. Luego, los lados ingresan al modo de sesión. En este modo, cualquiera de los lados puede enviar datos en cualquier momento, y dichos datos se reenvían hacia / desde el shell o comando en el lado del servidor y el terminal de usuario en el lado del cliente.

Opciones para restringir las funciones SSH

Los archivos y sus opciones que alteran el comportamiento son:

  • ~/.ssh/authorized_keys – contiene keys a los que se les permite conectarse a los que se les pueden dar opciones:
    • command="command" – Se ignora el comando proporcionado por el usuario (si lo hay). Tenga en cuenta que el cliente puede especificar el reenvío de TCP y / o X11 a menos que estén explícitamente prohibidos. Tenga en cuenta que esta opción se aplica a la ejecución de shell, comando o subsistema.
    • no-agent-forwarding – Prohíbe el reenvío del agente de autenticación cuando este key se utiliza para la autenticación.
    • no-port-forwarding – Prohíbe el reenvío de TCP cuando esto key se utiliza para la autenticación
    • no-X11-forwarding – “Prohíbe el reenvío X11 cuando este key se utiliza para la autenticación “.
    • permitopen="host:port" – Limite el reenvío de puerto local ‘ssh -L’ de modo que solo pueda conectarse al host y puerto especificados.
  • ~/.ssh/environment – Este archivo se lee en el entorno al iniciar sesión (si existe). El procesamiento del entorno está deshabilitado de forma predeterminada y se controla a través de la opción PermitUserEnvironment
  • ~/.ssh/rc – Contiene rutinas de inicialización que se ejecutarán antes de que se pueda acceder al directorio de inicio del usuario.
  • /etc/ssh/sshd_config – el archivo de configuración de todo el sistema
    • AllowAgentForwarding – Especifica si se permite el reenvío de ssh-agent (1).
    • AllowTcpForwarding
    • ForceCommand – “Fuerza la ejecución del comando especificado por ForceCommand, ignorando cualquier comando proporcionado por el cliente y ~ / .ssh / rc si está presente. El comando se invoca utilizando el shell de inicio de sesión del usuario con la opción -c”.
    • GatewayPorts – “Especifica si los hosts remotos pueden conectarse a los puertos reenviados para el cliente. De forma predeterminada, sshd (8) vincula los reenvíos de puertos remotos a la dirección de loopback. Esto evita que otros hosts remotos se conecten a los puertos reenviados. GatewayPorts se puede usar para especificar que sshd debería permitir que los reenvíos de puertos remotos se vinculen a direcciones que no sean de bucle invertido, permitiendo así que otros hosts se conecten “.
    • PermitOpen:

      Especifica los destinos a los que se permite el reenvío de puertos TCP. La especificación de reenvío debe ser una de las siguientes formas:

      PermitOpen host:port
      PermitOpen IPv4_addr:port
      PermitOpen [IPv6_addr]:port
      

      Se pueden especificar varios reenvíos separándolos con espacios en blanco. Se puede usar un argumento de ‘cualquiera’ para eliminar todas las restricciones y permitir cualquier solicitud de reenvío. De forma predeterminada, se permiten todas las solicitudes de reenvío de puertos.

    • PermitTunnel – Especifica si se permite el reenvío de dispositivos tun (4). El valor predeterminado es ‘no’
    • X11Forwarding – Especifica si se permite el reenvío X11. El valor predeterminado es ‘no’

Aplicando las restricciones

Modificar el archivo de configuración de todo el sistema /etc/ssh/sshd_config permite que la configuración se aplique incluso si se aplica la autenticación basada en contraseña o si las restricciones en ~/.ssh/authorized_keys se eliminan accidentalmente. Si ha modificado los valores predeterminados globales, debe descomentar las opciones en consecuencia.

Match User limited-user
   #AllowTcpForwarding yes
   #X11Forwarding no
   #PermitTunnel no
   #GatewayPorts no
   AllowAgentForwarding no
   PermitOpen localhost:62222
   ForceCommand echo 'This account can only be used for [reason]'

Ahora agregue un usuario:

sudo useradd -m limited-user

La opción ForceCommand se puede omitir si el shell se establece en un no similar a shell /bin/false (o /bin/true) como /bin/false -c [command] no hará nada.

Ahora el cliente solo puede conectarse al puerto 62222 en la dirección de loopback del servidor a través de SSH (no escuchará en la dirección IP pública)

Inhabilitando AllowTcpForwarding también prohibiría el uso de -R, derrotando así el uso de una cuenta tan restringida para reenviar un solo puerto. PermitOpen localhost:62222 asume que el puerto 62222 en el servidor nunca está en uso porque el cliente puede conectarse felizmente y escucharlo también.

Si se permite el reenvío de TCP en la configuración de todo el sistema y se deshabilita la autenticación basada en contraseña, puede usar per-key configuraciones también. Editar ~/.ssh/authorized_keys y agregue las siguientes opciones antes de ssh- (con un espacio entre las opciones y ssh-):

command="echo 'This account can only be used for [reason]'",no-agent-forwarding,no-X11-forwarding,permitopen="localhost:62222"

Verificar

Para asegurarse de que funciona como se esperaba, es necesario ejecutar algunos casos de prueba. En los siguientes comandos, host debe ser reemplazado por el inicio de sesión real si no está configurado en ~/.ssh/config. Detrás del comando, se muestra un comando que debe ejecutarse en el cliente o en el servidor (como se especifica).

# connection closed:
ssh host
# connection closed (/bin/date is not executed):
ssh host /bin/date
# administratively prohibited (2x):
ssh host -N -D 62222 # client: curl -I --socks5 localhost:62222 example.com
ssh host -N -L 8080:example.com:80 # client: curl -I localhost:8080
sftp host
# should be possible because the client should forward his SSH server
ssh host -N -R 8080:example.com:80 # server: curl -I localhost:8080
# This works, it forwards the client SSH to the server
ssh host -N -R 62222:localhost:22
# unfortunately, the client can listen on that port too. Not a big issue
ssh host -N -L 1234:localhost:62222

Conclusión

Lista de comprobación: el usuario de SSH no debería poder:

  • ejecutar comandos de shell – hecho
  • acceder a archivos o cargar archivos en el servidor – hecho
  • utilizar el servidor como proxy (por ejemplo, webproxy) – hecho
  • acceder a servicios locales que de otro modo no serían accesibles públicamente debido a un firewall – parcialmente, el cliente no puede acceder a otros puertos que no sean 62222, pero puede escuchar y conectarse al puerto 62222 en el servidor
  • matar al servidor – hecho
    (tenga en cuenta que estas comprobaciones se limitan al servidor SSH. Si tiene otro servicio vulnerable en la máquina, podría permitir que un posible atacante ejecute comandos, elimine el servidor, etc.)

Estoy seguro de que hay muchas soluciones para esto, y muchas más robustas que la que propongo. Sin embargo, esto puede ser suficiente para sus necesidades. Para hacerlo, supongo que el usuario puede hacer ssh key autenticación basada (putty o cualquier ssh de Unix debería admitir esto).

  • Agregue un usuario como lo haría normalmente (‘adduser’ o cualquier otra herramienta)

  • Cree el directorio .ssh de los usuarios y .ssh / allowed_keys

your_user $ sudo -Hu ssh_forwarder /bin/bash

ssh_forwarder $ cd ~
ssh_forwarder $ mkdir .ssh
ssh_forwarder $ ( umask 066 && cat > .ssh/authorized_keys ) <[email protected]
EOF
  • Desactive el acceso con contraseña a esta cuenta.
your_user $ sudo usermod --lock ssh_forwarder

Ahora, la única forma en que el usuario puede ingresar a su sistema es a través del acceso al ssh adecuado key, y ssh ejecutará “/ bin / bash -c ‘read a'” para ellos, sin importar lo que intenten ejecutar. ‘read a’ simplemente leerá hasta una nueva línea, y luego el shell saldrá, por lo que el usuario solo tiene que presionar ‘enter’ para cerrar la conexión.

Hay muchas otras cosas que puede hacer en ‘command =’. Ver man authorized_keys y busque “comando” para obtener más información.

Si no le gusta el hecho de que presionar enter mata la conexión, puede usar algo como lo siguiente para la entrada ‘command =’:

command="f=./.fifo.$$ && mkfifo $f && trap "rm -f $f" EXIT && read a <$f && echo $a; exit;"

Esto solo crea un filtro temporal en el directorio de inicio de los usuarios y luego intenta leerlo. No se escribirá nada en ese archivo, por lo que se bloqueará indefinidamente. Además, si desea terminar esa conexión a la fuerza, puede hacer algo como:

 your_user$ echo GOODBYE | sudo tee ~ssh_forwarder/.fifo.*

Esto debería usar muy pocos recursos, y nada debería salir mal en ese script que no terminaría en la terminación del shell.

sleep 1h; echo You have been here too long. Good bye.

No vi de improviso cómo se podía permitir al usuario reenviar de forma remota (ssh -R) pero limitar (ssh -L). Quizás se podría usar 'permitopen'. Buscar en Google no fue muy útil. Parecería que algo como 'sin reenvío de puertos, permitremoteopen = 10001' sería útil para permitir ssh -R 6901:localhost:6901.

Este es a solución. Definitivamente se puede mejorar, y cualquier apertura de puertos remotos debe ser examinada. Si mi objetivo era permitir que mi abuela se conectara a mi LAN para poder usar vnc para ver su pantalla y acceder a esos keys estaba limitado a ella, personalmente me sentiría razonablemente seguro. Si se trataba de una empresa, sería necesaria una investigación más exhaustiva. Una cosa a tener en cuenta es ssh -N no solicita un shell en absoluto, por lo que el código 'command =' no se ejecuta.

Otros mecanismos posiblemente más seguros pueden incluir la creación de un shell personalizado para el usuario, e incluso bloquearlo con apariencia.

Si entiendes que te ha resultado provechoso este artículo, nos gustaría que lo compartas con más programadores de esta manera contrubuyes a dar difusión a nuestra información.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *