Una gran aplicación necesita, en un momento específico, realizar una pequeña cantidad de escrituras en un archivo que requiere permisos de root. No es realmente un archivo, sino una interfaz de hardware que está expuesta a Linux como un archivo.
Para evitar otorgar privilegios de root a toda la aplicación, escribí un script bash que realiza las tareas críticas. Por ejemplo, el siguiente script habilitará el puerto 17 de la interfaz de hardware como salida:
echo "17" > /sys/class/gpio/export
echo "out" > /sys/class/gpio/gpio17/direction
Sin embargo, como suid
está deshabilitado para los scripts de bash en mi sistema, me pregunto cuál es la mejor manera de lograrlo.
Use alguna solución presentada aquí
Llame al script
sudo
desde la aplicación principal y edite la lista de sudoers en consecuencia, para evitar requerir una contraseña al llamar al script. Me incomoda un poco dar privilegios de sudoecho
.Simplemente escriba un programa en C, con
fprintf
, y configúrelo en suid root. Codifique las cadenas y los nombres de archivo y asegúrese de que solo root pueda editarlo. O lea las cadenas de un archivo de texto, de manera similar, asegurándose de que nadie pueda editar el archivo.¿Alguna otra solución que no se me ocurrió y es más segura o más simple que las presentadas anteriormente?
fuente
Respuestas:
No necesita dar
sudo
acceso aecho
. De hecho, eso no tiene sentido porque, por ejemplo, consudo echo foo > bar
, la redirección se realiza como el usuario original, no como root.Llame al script pequeño con
sudo
, permitiendo elNOPASSWD:
acceso a SOLO ese script (y cualquier otro script similar) por el usuario (s) que necesitan acceso a él.Esta es siempre la mejor / más segura forma de usar
sudo
. Aísle la pequeña cantidad de comandos que necesitan privilegios de root en sus propios scripts separados y permita que el usuario no confiable o parcialmente confiable solo ejecute ese script como root.El
sudo
script (s) pequeño -o no debe tomar argumentos (o entradas) del usuario (es decir, cualquier otro programa que llame debe tener opciones codificadas y argumentos) o debe validar con mucho cuidado cualquier argumento / entrada que tenga que aceptar del usuarioSea paranoico en la validación: en lugar de buscar cosas 'conocidas malas' para excluir, permita solo cosas 'conocidas buenas' y anule cualquier desajuste o error o cualquier cosa remotamente sospechosa.
La validación debe ocurrir tan pronto como sea posible en el script (preferiblemente antes de que haga otra cosa como root).
Yo realmente debería haber mencionado esto cuando empecé a escribir esta respuesta, pero si el script es un script de shell que DEBO citar correctamente todas las variables. Tenga especial cuidado en citar variables que contengan datos proporcionados por el usuario de alguna manera, pero no asuma que algunas variables son seguras, COTIZAR TODAS .
Eso incluye variables de entorno potencialmente controladas por el usuario (p
"$PATH"
. Ej ."$HOME"
,"$USER"
Etc. Y definitivamente incluye"$QUERY_STRING"
y"HTTP_USER_AGENT"
etc. en un script CGI). De hecho, solo cítelos a todos. Si tiene que construir una línea de comando con múltiples argumentos, use una matriz para construir la lista de argumentos y cite eso -"${myarray[@]}"
.¿Ya he dicho "citarlos a todos" con bastante frecuencia? recuerdalo. hazlo.
fuente
Verifique el propietario en los archivos gpio:
Lo más probable es que descubras que son propiedad del grupo
gpio
:En ese caso, simplemente puede agregar su usuario al
gpio
grupo para otorgar acceso sin sudo:Deberá cerrar sesión y volver a iniciarla después de eso para que el cambio surta efecto.
fuente
/sys/class/gpio/
gpio es, pero incluso después de agregarme a ese grupo, todavía recibo "permiso denegado" cada vez que intento escribir algo allí./sys/class/gpio/
realidad son solo enlaces simbólicos a/sys/devices/platform/soc/<some temporary name>/gpio
donde tanto el propietario como el grupo son root.chgrp gpio /sys/devices/platform/soc/*/gpio
? Quizás algo así podría colocarse en un archivo de inicio.chgrp gpio `readlink -f /sys/class/gpio/gpio18`/*
Una solución para esto (usada particularmente en el escritorio de Linux pero también aplicable en otros casos) es usar D-Bus para activar un pequeño servicio que se ejecuta como root y polkit para hacer la autorización. Esto es fundamentalmente para lo que fue diseñado polkit ; de su documentación introductoria :
En lugar de ejecutar su programa de ayuda, el programa grande y sin privilegios enviaría una solicitud en el bus. Su ayudante podría estar ejecutándose como un demonio iniciado en el arranque del sistema o, mejor aún, ser activado según sea necesario por systemd . Luego, ese ayudante usaría polkit para verificar que la solicitud proviene de un lugar autorizado. (O, en este caso, si eso parece excesivo, podría usar algún otro mecanismo de autenticación / autorización codificado).
Encontré un buen artículo básico sobre comunicación a través de D-Bus , y aunque no lo he probado, este parece ser un ejemplo básico de agregar polkit a la mezcla .
En este enfoque, nada necesita ser marcado como setuid.
fuente
Una forma de hacer esto es hacer un programa setuid-root escrito en C que solo haga lo que se necesita y nada más. En su caso, no tiene que mirar ninguna entrada del usuario.
No hay forma de subvertir esto a través de variables de entorno ni nada, porque todo lo que hace es hacer un par de llamadas al sistema.
Desventaja: debe verificar el valor de retorno de cada llamada al sistema.
Al revés: la comprobación de errores es realmente fácil: si hay algún error, solo
perror
y rescatar: salga con un estado distinto de cero. Si hay un error, investigue constrace
. No necesita este programa en sí mismo para dar mensajes de error realmente agradables.fuente
sudo
para que no sea necesario configurarlo. Por cierto, es<fcntl.h>
paraopen()
.Bendice tee en lugar de echo para sudo es una forma común de abordar una situación en la que debes limitar las permanentes. La redirección a / dev / null es detener cualquier salida que se filtre: el tee hace lo que desea.
fuente
tee
que se ejecute consudo
, está permitiendo que CUALQUIER archivo se sobrescriba o/etc/passwd
anexe (incluyendo, por ejemplo, - solo agregue una nueva cuenta uid = 0). También puede permitir que se ejecuten todos los comandossudo
(BTW/etc/sudoers
pertenece al conjunto de 'CUALQUIER archivo', por lo que puede sobrescribirse consudo tee
)tee
puede escribir, como se describe en esta respuesta en una pregunta separada. Solo asegúrese de leer los comentarios también, ya que algunas personas tuvieron problemas con la sintaxis original utilizada y sugieren soluciones a ese problema.tee
o lo que sea para operar en muchos archivossudo
.Puede hacer un script que realice su tarea deseada. Luego, cree una nueva cuenta de usuario que solo pueda iniciar sesión proporcionando una clave utilizada por OpenSSH.
Nota: Cualquiera podrá ejecutar ese script si tiene el archivo de clave, así que asegúrese de que el archivo de clave de OpenSSH no sea legible por nadie que desee evitar que realice la tarea.
En la configuración de OpenSSH (en el archivo autorizado_claves), antes de especificar la clave, especifique un comando (seguido de un espacio), como se describe en este texto de "ejemplo":
command="myscript" keydata optionalComment
Esta opción de configuración puede restringir esa clave OpenSSH para que solo ejecute un comando específico. Ahora tiene sudo otorgando los permisos, pero la configuración de OpenSSH es la pieza de la solución que realmente se está utilizando para restringir / limitar lo que ese usuario puede hacer, de modo que el usuario no esté ejecutando otros comandos. Esto tampoco tiene un archivo de configuración "sudo" tan complicado, así que si usa OpenBSD o si las nuevas "doas" ("do as") de OpenBSD comienzan a ser más populares (con futuras versiones de cualquier sistema operativo que use) , no necesitará ser desafiado por mucha complejidad en la configuración de sudo.
fuente