¿Cómo pasar con seguridad las variables a los scripts habilitados para root?

13

Esta pregunta es totalmente general y no solo se aplica a mi situación, sino que ... Tengo un pequeño dispositivo busybox donde quiero que un usuario no root pueda ejecutar un script en particular con privilegios de root. Por ejemplo, algo así como este pequeño script para habilitar DHCP, donde la única variable ( $1) para enviar en la línea de cm (!!) es qué nombre de host enviar:

#!/bin/bash
udhcpc -b -i eth0 -h $1

ejecutar udhcpc de esta manera requiere acceso de root, por lo que para hacer esto planeo modificar /etc/sudoerspara contener esta línea:

joe ALL = NOPASSWD: /path/to/enable_dhcp.sh

que debería permitir que "joe" ejecute fácilmente ese script con privilegios de root simplemente ejecutando:

sudo /path/to/enable_dhcp.sh

y no se me pide una contraseña (que es lo que quiero, ya que quiero que Joe pueda escribir esto).

Ahora ... (o al menos creo que lo hago) que usar $1un script que se puede ejecutar fácilmente con privilegios de root es una idea HORRIBLE ya que puedes inyectar lo que quieras en eso.

Entonces ... ¿cuál es la mejor manera de lidiar con esto? ¿Cómo dejo que Joe haga lo que quiero con los privilegios de root, permitirle pasar una variable (o efectivamente hacerlo como con una variable de entorno), sin estar abierto a ataques de inyección?

Russ
fuente

Respuestas:

14

La ejecución de scripts de shell sudoes segura siempre que sudoesté configurada para restablecer el entorno . Por el contrario, si sudono restablece el entorno, ejecutar un script de shell no es seguro, incluso si su script no utiliza sus parámetros (consulte Permitir setuid en los scripts de shell ). Asegúrese de que usted tiene Defaults env_reseten /etc/sudoerso que esta opción es el valor predeterminado de tiempo de compilación ( sudo sudo -V | grep envdebe incluir Reset the environment to a default set of variables).

No existe un peligro particular al usar los parámetros del script. $1es una cadena, todo lo que necesita para asegurarse es que la esté usando como una cadena. (Por ejemplo, no lo haga eval "$1"). Obviamente, es especialmente importante aquí no hacer suposiciones sobre el contenido de la variable y poner comillas dobles alrededor de todas las sustituciones de variables (es decir "$1", escribir , no $1). Tenga en cuenta que poner comillas dobles alrededor de las sustituciones variables no es específico para los scripts que se ejecutan con privilegios, es algo que debe hacer todo el tiempo.

Es posible que desee validar el parámetro aún más, dependiendo de lo que udhcpchaga con algo que no se parece a un nombre de host. Por ejemplo, esto realizará una primera verificación sintáctica:

#!/bin/sh
case "$1" in
  *[!:-.0-9A-Za-z]*|-*) echo 1>&2 "Badly formed host name!"; exit 3;;
esac
udhcpc -b -i eth0 -h "$1"
Gilles 'SO- deja de ser malvado'
fuente
Otras cosas a tener en cuenta que podrían tener un impacto en el comportamiento de ese comando: el directorio de trabajo actual y a qué apuntan stdin, stdout, stderr, controladores de señales y ulimits. Por ejemplo, al permitir volcados de núcleo (en <kbd> Ctrl- \ </kbd>), podría permitir al usuario arrojar basura / ejecutar / bloquear lo que en mi sistema es un tmpfs con un tamaño muy limitado y podría permitir un DoS.
Stéphane Chazelas
5

Debe hacer coincidir la entrada pasada con un patrón conocido.

Por ejemplo, parece que una dirección IP podría ser una entrada válida para usted. Entonces podrías usar algo como esto:

if [[ "$1" =~ ^[0-9]?[0-9]?[0-9].[0-9]?[0-9]?[0-9].[0-9]?[0-9]?[0-9]$ ]]
then
  udhcpc -b -i eth0 -h "$1"
else
  echo "Don't mess with me pork chop."
fi

Tenga en cuenta que regexp no ha sido probado, usted es responsable de asegurarse de que su regexp no permita nada peligroso.

bahamat
fuente