GNU/Linux >> Tutoriales Linux >  >> Linux

¿Usando el bit Setuid correctamente?

Tengo un proceso que necesita privilegios de root cuando lo ejecuta un usuario normal. Aparentemente puedo usar el "bit setuid" para lograr esto. ¿Cuál es la forma correcta de hacer esto en un sistema POSIX?

Además, ¿cómo puedo hacer esto con un script que usa un intérprete (bash, perl, python, php, etc.)?

Respuesta aceptada:

El bit setuid se puede configurar en un archivo ejecutable para que, cuando se ejecute, el programa tenga los privilegios del propietario del archivo en lugar del usuario real, si son diferentes. Esta es la diferencia entre efectivo uid (identificación de usuario) y real líquido.

Algunas utilidades comunes, como passwd , son propiedad de root y están configurados de esta manera por necesidad (passwd necesita acceder a /etc/shadow que solo puede ser leído por root).

La mejor estrategia al hacer esto es hacer lo que necesite hacer como superusuario de inmediato y luego reducir los privilegios para que sea menos probable que ocurran errores o mal uso mientras se ejecuta la raíz. Para hacer esto, configura el proceso efectivo uid a su uid real. En POSIX C:

#define _POSIX_C_SOURCE 200112L // Needed with glibc (e.g., linux).
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

void report (uid_t real) {
    printf (
        "Real UID: %d Effective UID: %dn",
        real,
        geteuid()
    );
}

int main (void) {
    uid_t real = getuid();
    report(real);
    seteuid(real);
    report(real);
    return 0;
}

Las funciones relevantes, que deberían tener un equivalente en la mayoría de los lenguajes de nivel superior si se usan comúnmente en sistemas POSIX:

  • getuid() :Obtén lo real líquido.
  • geteuid() :Obtenga el efectivo líquido.
  • seteuid() :establezca el efectivo líquido.

No puede hacer nada con el último inapropiado para el uid real excepto en la medida en que el bit setuid se configuró en el ejecutable . Entonces, para probar esto, compile gcc test.c -o testuid . Entonces necesita, con privilegios:

chown root testuid
chmod u+s testuid

El último establece el bit setuid. Si ahora ejecuta ./testuid como usuario normal, verá que el proceso se ejecuta de forma predeterminada con uid efectivo 0, root.

¿Qué pasa con los guiones?

Esto varía de una plataforma a otra, pero en Linux, las cosas que requieren un intérprete, incluido el código de bytes, no pueden usar el bit setuid a menos que esté configurado en el intérprete (lo que sería muy, muy estúpido). Aquí hay un script perl simple que imita el código C anterior:

#!/usr/bin/perl
use strict;
use warnings FATAL => qw(all);

print "Real UID: $< Effective UID: $>n";
$> = $<; # Not an ASCII art greedy face, but genuine perl...
print "Real UID: $< Effective UID: $>n"; 

Fiel a sus raíces *nixy, perl ha incorporado variables especiales para uid efectivo ($> ) y uid real ($< ). Pero si pruebas el mismo chown y chmod usado con el ejecutable compilado (de C, ejemplo anterior), no hará ninguna diferencia. El script no puede obtener privilegios.

Relacionado:¿Cómo actualizar bash a v4.0+ correctamente?

La respuesta a esto es usar un binario setuid para ejecutar el script:

#include <stdio.h>
#include <unistd.h> 

int main (int argc, char *argv[]) {
    if (argc < 2) {
        puts("Path to perl script required.");
        return 1;
    }
    const char *perl = "perl";
    argv[0] = (char*)perl;
    return execv("/usr/bin/perl", argv);
}

Compile este gcc --std=c99 whatever.c -o perlsuid , luego chown root perlsuid && chmod u+s perlsuid . Ahora puede ejecutar cualquier secuencia de comandos perl con un uid efectivo de 0, independientemente de quién sea el propietario.

Una estrategia similar funcionará con php, python, etc. Pero...

# Think hard, very important:
>_< # Genuine ASCII art "Oh tish!" face

POR FAVOR NO dejes este tipo de cosas por ahí . Lo más probable es que desee compilar el nombre del script como una ruta absoluta. , es decir, reemplaza todo el código en main() con:

    const char *args[] = { "perl", "/opt/suid_scripts/whatever.pl" }
    return execv("/usr/bin/perl", (char * const*)args);

Ellos se aseguran de que /opt/suid_scripts y todo lo que contiene es de solo lectura para usuarios no root. De lo contrario, alguien podría intercambiar cualquier cosa por whatever.pl .

Además, tenga en cuenta que muchos lenguajes de secuencias de comandos permiten que las variables de entorno cambien la forma en que ejecutan una secuencia de comandos . Por ejemplo, una variable de entorno puede hacer que se cargue una biblioteca proporcionada por la persona que llama, lo que permite que la persona que llama ejecute código arbitrario como raíz. Por lo tanto, a menos que sepa que tanto el intérprete como el script en sí son robustos frente a todas las variables de entorno posibles, NO HAGA ESTO .

Entonces, ¿qué debo hacer en su lugar?

Una forma más segura de permitir que un usuario no root ejecute un script como root es agregar una regla sudo y hacer que el usuario ejecute sudo /path/to/script . Sudo elimina la mayoría de las variables de entorno y también permite que el administrador seleccione con precisión quién puede ejecutar el comando y con qué argumentos. Consulte ¿Cómo ejecutar un programa específico como root sin solicitar una contraseña? para un ejemplo.


Linux
  1. ¿Propósito de usar Setuid() en programas Suid?

  2. ¿El beneficio real de usar Uuids?

  3. Usando la Interfaz Universal de Ajedrez

  4. Ejecutar una aplicación Qt en la web

  5. SELinux en el mundo real

Consejos para usar el comando superior en Linux

Usando el comando libre de Linux

Uso del archivo de configuración SSH

Tutorial sobre el uso del comando Timeout en Linux

Tutorial sobre el uso del último comando en la terminal de Linux

¿Cuál es la sobrecarga de usar subcapas?