Uso de CmndAlias ALL
nunca estará a salvo
Hay 1000 formas de ejecutar service network restart
sin hacer sudo service network restart
. Este es un ejemplo de lo que podría intentar un usuario travieso:
$ echo "service network restart" > /tmp/hax
$ chmod a+x /tmp/hax
$ sudo /tmp/hax
Si proporciona a los usuarios el ALL
alias de comando, y luego intente crear una lista negra, siempre podrán encontrar una forma de evitarlo. Blacklist bash, y usarán python. Python en la lista negra, y usarán Perl. Lista negra de Perl, y usarán PHP. ¡Nadie quiere eso!
Si realmente no quieres que alguien haga algo, debes hacer lo que dice Thomas y crear una lista blanca de las cosas que son. permitido hacer.
Configurar una lista blanca con una excepción
Puede encontrar un ejemplo de una pequeña lista blanca con una exclusión cerca de la parte inferior de man sudoers
:
pete HPPA = /usr/bin/passwd [A-Za-z]*, !/usr/bin/passwd root
The user pete is allowed to change anyone's password except for root on the HPPA
machines. Note that this assumes passwd(1) does not take multiple user names
on the command line.
(De hecho, este ejemplo de la página de manual no es seguro y se puede explotar para cambiar la contraseña de root. Consulte los comentarios a continuación para saber cómo).
Podemos intentar adaptar eso a tu caso, para ofrecerte todos los service
comandos al grupo de personal, pero excluir el service network
comandos que le conciernen:
%staff ALL = /usr/sbin/service *, \
! /usr/sbin/service *network*, \
! /usr/sbin/service *NetworkManager*
(El ALL
en esa posición se refiere a Host_Alias, no a Cmnd_Alias, ¿no es confuso?)
El usuario no podrá ejecutar sudo bash
o sudo tee
o sudo wget
o sudo /path/to/malicious_script
. Puede incluir en la lista blanca más comandos de administrador para sus usuarios si tiene cuidado. ¡Solo sé específico!
Nota:agregué el *
antes de la palabra network
anterior, en caso de que alguna vez se agregue una bandera inofensiva al service
herramienta en el futuro. Imaginemos un --verbose
se agregó la bandera en el futuro, entonces los usuarios podrían ejecutar lo siguiente:
$ sudo service --verbose network restart
Entonces necesitamos el *
para consumir cualquier indicador antes del nombre del servicio. La única desventaja es que esto podría bloquear otros servicios que en realidad no le importa que los usuarios ejecuten, p. un servicio llamado safe-network
o network-monitor
también sería rechazado.
Permitir que los usuarios editen un archivo usando permisos de grupo
A continuación puede encontrar varios intentos usando rnano
a través de sudo
para permitir que los usuarios editen un archivo o archivos. Pero en realidad son más complejos y más peligrosos de lo que deberían ser.
Una solución mucho más simple y segura es cambiar los permisos de grupo en los archivos específicos para los que desea abrir derechos de edición. Aquí hay un par de ejemplos:
### Give steve the ability to edit his nginx config:
$ chgrp steve /etc/nginx/sites-available/steves_dodgy_project
$ chmod g+rw /etc/nginx/sites-available/steves_dodgy_project
### Let all members of the staff group edit the group_website config:
$ chgrp staff /etc/nginx/sites-available/group_website
$ chmod g+rw /etc/nginx/sites-available/group_website
Si necesita un control más detallado (por ejemplo:acceso para solo 3 usuarios, pero no para todos los miembros del personal), puede crear un nuevo grupo usando el addgroup
y agregue solo algunos usuarios.
Permitir que los usuarios editen un archivo mediante sudo
El resto de esta respuesta se convirtió en una investigación sobre lo fácil que es dejar agujeros en tu sudo
configuración al intentar ofrecer flexibilidad a sus usuarios. ¡No recomendaría hacer nada de lo siguiente!
Si desea otorgar a sus usuarios acceso para editar un archivo específico, puede intentar usar rnano
:
%staff ALL = /bin/rnano /etc/nginx/sites-available/host
rnano
solo les permitirá editar el archivo especificado. Eso es importante para evitar que un usuario malintencionado edite un servicio advenedizo diferente (por ejemplo, /etc/init.d/urandom
) y agregarle una línea que ejecutaría service network restart
.
Desafortunadamente, no encontré una forma de restringir rvim
suficientemente (el usuario aún puede abrir cualquier archivo usando :e
), por lo que estamos atascados con nano
.
Lamentablemente, permitir que los usuarios editen varios archivos es mucho más difícil...
Permita que los usuarios editen varios archivos (mucho más difícil de lo que debería ser)
1. Enfoques inseguros
¡Cuidado con los comodines! Si ofrece demasiada flexibilidad (o cualquier flexibilidad), se puede explotar:
%staff ALL = /bin/rnano /etc/nginx/sites-available/* # UNSAFE!
En este caso, un usuario malintencionado podría editar cualquier otro script de servicio advenedizo y luego ejecutarlo:
$ sudo rnano /etc/nginx/sites-available/../../../any/file/on/the/system
(Sudo en realidad previene .
y ..
expansión en el comando, pero desafortunadamente no en los argumentos).
Esperaba que algo como esto pudiera funcionar, pero sigue siendo inseguro:
%staff ALL = /bin/rnano /etc/nginx/sites-available/[A-Za-z0-9_-]* # UNSAFE!
Desde sudo
actualmente solo ofrece glob patrones, que *
coincidirá con cualquier cosa - ¡no es una expresión regular!
(Editar:consideré si podrías salirse con la suya en su situación, porque no hay subcarpetas debajo de sites-available
. Exigimos que coincidiera un carácter después de la carpeta, y /..
debería fallar después de un nombre de archivo. Sin embargo, esta no es una solución viable, porque rnano
acepta múltiples argumentos. Y de todos modos, en general, esto seguiría siendo inseguro en una carpeta que tenía subcarpetas!)
Incluso si no tenemos subcarpetas y excluimos cualquier línea que contenga /../
, la regla que ofrece un *
glob aún podría ser explotado, porque rnano
acepta múltiples argumentos (recorriéndolos en <C-X>
, y el espacio es felizmente aceptado por el *
globo.
$ rnano /etc/nginx/sites-available/legal_file /then/any/file/on/the/system
2. Empujando el sobre (también inseguro en última instancia)
Entonces, ¿qué sucede si rechazamos cualquier línea que contenga espacios o que intente llegar a /..
? ? Entonces, una solución viable final podría ser esta:
# I tried hard to make this safe, but in the end I failed again.
# Please don't use this unless you are really smart or really stupid.
%staff ALL = /bin/rnano /etc/nginx/sites-available/*, \
! /bin/rnano */..*, \
! /bin/rnano /etc/nginx/sites-available/, \
! /bin/rnano */., \
! /bin/rnano * *
# CONCLUSION: It is still NOT SAFE if there are any subfolders, due to
# the bug in rnano described below.
Aceptamos cualquier cosa "debajo" de la carpeta pero también rechazamos cualquier llamada a rnano
si /..
o /.
o se pasan, o si la carpeta está dirigida directamente. (Técnicamente el
/.
la exclusión hace que el /..
exclusión redundante, pero he dejado ambas para mayor claridad).
Encontré la carpeta y el /.
se necesitaban exclusiones porque, de lo contrario, el usuario podría apuntar a la carpeta en sí. Ahora podrías pensar rnano
bloquearía si apuntara a una carpeta, pero estaría equivocado. En realidad, mi versión (2.2.6-1ubuntu1) se inicia con una advertencia leve y un archivo vacío, luego en <C-X>
me pide que ingrese cualquier nombre de archivo que me guste para guardar, abriendo un nuevo vector de ataque! Bueno, al menos se negó a sobrescribir un archivo existente (en la única prueba que hice). De todos modos, dado que no hay forma de incluir en la lista negra las subcarpetas con sudo, debemos concluir que este enfoque nuevamente no es seguro. ¡Lo sentimos usuarios!
Este descubrimiento me hizo dudar de la minuciosidad de nano
Modo "restringido" de . Dicen que una cadena es tan fuerte como su eslabón más débil. Estoy empezando a sentir la combinación de sudo
lista negra magia negra y rnano
puede que no sea más seguro que una cadena de margaritas.
3. Enfoques seguros pero limitados
Los globos están muy restringidos:no nos permiten hacer coincidir una clase de personaje varias veces. podrías ofrecer varias ediciones de archivos, si todos los nombres de archivo tienen la misma longitud (en este caso, host
) seguido de un solo dígito):
%staff ALL = /bin/rnano /etc/nginx/sites-available/host[0-9] # SAFE
Pero si desea otorgar al usuario acceso para editar varios archivos, es posible que deba especificar todos y cada uno de los archivos explícitamente:
%staff ALL = /bin/rnano /etc/nginx/sites-available/hothost \
/bin/rnano /etc/nginx/sites-available/coldhost \ # SAFE
/bin/rnano /etc/nginx/sites-available/wethost \
/bin/rnano /etc/nginx/sites-available/steves_dodgy_project
No se deje tentar usar un *
en cualquier punto. Consulte las secciones 1 y 2 anteriores para saber por qué. Recuerde:un pequeño desliz puede comprometer toda la cuenta de superusuario y todo el sistema.
4. Escribe tu propio verificador de argumentos (la seguridad ahora es tu responsabilidad)
Espero que agreguen compatibilidad con expresiones regulares a sudo
en el futuro; podría resolver muchos problemas si se usa correctamente. Pero también es posible que necesitemos la capacidad de verificar las propiedades de los argumentos (para permitir solo archivos, solo carpetas o solo ciertas banderas).
Pero hay una alternativa para crear flexibilidad en sudo. Pasa la pelota:
%staff ALL = /root/bin/staffedit *
Luego escribe tu propio staffedit
script o ejecutable para verificar si los argumentos pasados por el usuario son legales, y solo llevar a cabo su solicitud si lo son.
Primero, abra el archivo sudoers con sudo visudo
. Agregando user ALL=!/usr/sbin/service
el IIRC rechazará el service
comando para el usuario user
.
Fuentes:http://nixcraft.com/showthread.php/15132-Sudo-Exclude-Commands-And-Disable-sudo-su-Bash-Shell
He encontrado la solución.
Abrí la terminal y cambié a usuario root con su -
entonces he escrito visudo
para editar.
luego al final he escrito lineas como
user ALL=!/etc/init.d/NetworkManager restart
user ALL=!/etc/init.d/network restart
Luego guardé y cerré y reinicié también.
Ahora si estoy escribiendo como service network restart
o service NetworkManager restart
entonces no me permite y da un error como
Sorry user is not allowed to execute '/sbin/service NetowkrManager restart' as root on localhost.localdomain
y de manera similar para service network restart
mando también.