Estoy escribiendo algunos software (en C++ para Linux/Mac OSX), que se ejecuta como un usuario sin privilegios, pero necesita privilegios de root en algún momento (para crear un nuevo dispositivo virtual).

Ejecutar este programa como root no es una opción (principalmente por cuestiones de seguridad) y necesito saber la identidad (uid) de la «real» del usuario.

Es allí una manera de imitar el «sudo» comportamiento de comando (pide contraseña de usuario) temporalmente obtener privilegios de root y realizar la tarea en particular ? Si es así, qué funciones puedo utilizar ?

Muchas gracias por tu ayuda !

InformationsquelleAutor ereOn | 2010-03-20

7 Comentarios

  1. 15

    Respuesta Original

    Usted podría considerar el setuid cambiar en el archivo ejecutable de la misma. Wikipedia tiene un artículo que incluso muestra la diferencia entre geteuid() y getuid() de manera bastante efectiva, siendo el primero para saber quién eres «emular» y el segundo, por lo que «son». El sudo proceso, por ejemplo, geteuid debe devolver 0 (root) y getuid su identificación de usuario, sin embargo, sus sub-procesos verdaderamente ejecutar como root (usted puede verificar esto con sudo id -u -r).

    Creo que no hay una manera fácil mediante programación obtener acceso root – después de todo, la aplicación del principio de privilegio mínimo, ¿por qué usted necesita? Una práctica común es ejecutar sólo se limita partes de código con privilegios elevados. Un montón de demonios etc también se ha configurado bajo modernos sistemas para que se ejecute como su propio usuario con la mayoría de los privilegios que necesitan. Es sólo para operaciones muy específicas (montaje, etc) que los privilegios de root son realmente necesarios.

    2013 actualización

    Mi respuesta original se encuentra (aunque a mi de 2013 auto podría hacer un mejor trabajo de mi 2010), pero si está diseñando una aplicación que requiere acceso de root, puede que desee considerar exactamente qué tipo de acceso de root es necesario y considerar el uso de Capacidades de POSIX (el hombre de la página). Estos son diferentes a la capacidad de la seguridad basada en como se implementa en L4 et al. ESTAS capacidades permiten su aplicación para la concesión de un subconjunto de los poderes de root. Por ejemplo CAP_SYS_MODULE le permitirá insertar los módulos del kernel, pero no te darán otros poderes raíz. Esto está en uso en las distribuciones por ejemplo, Fedora tiene una función para eliminar completamente los binarios setuid indiscriminado acceso root.

    Esto es importante, porque como programador, el código es, obviamente, perfecto! Pero, las bibliotecas de la que dependen (suspiro, si sólo había escrito!) podría tener vulnerabilidades en ellos. El uso de las capacidades, usted puede limitar el uso de este exploit, y salvar a sí mismo y a su empresa de seguridad relacionadas con el escrutinio. Esto hace a todos más felices.

    • Sí, mi enfoque no fue el correcto. Ajuste el sticky-bit es la buena manera de hacer eso. Muchas gracias.
    • Funciona como un encanto ! Gracias 😉
    • Al hacer esto, usted tiene que ser es cuidado acerca de la seguridad, debido a que su aplicación es ahora un destino de Escalada de Privilegios explota
    • Al hacer esto, hacer las cosas que necesita privilegios de root tan pronto como sea posible y bajar a la real derecho de usuario después de eso.
    • Under sudo, for example, geteuid should return 0 (root) and getuid your user's id. Esto es falso. A ver mi pregunta con respecto a exactamente este problema: stackoverflow.com/questions/10272784/…
    • ah, sí. Sudo sí debe ser capaz de ver esas cosas, pero heredó procesos no. Sólo heredar el id de usuario efectivo como su id real del usuario. Voy a editar este, ya que no está claro.
    • Cuando hago esto en Mac OS X (Mountain Lion) me sale «La aplicación con el ID de paquete (null) se está ejecutando setugid(), lo cual no está permitido.» al intentar iniciar el programa. ¿Qué puedo hacer?
    • Yo no estoy familiarizado con OSX, sin embargo, recientemente ha habido un enfoque sobre la extracción de setuid/setgid como estas son automáticamente explotar los objetivos de los chicos malos, así que podría ser que esta es una característica de OSX. Has intentado buscar ASÍ? Si que apareció de la nada, pregunte a su propia pregunta. Yo estaría interesado en la respuesta!
    • la otra opción es para configurar el dispositivo de grupo de la propiedad utilizando las reglas de udev, y asegurarse de que el usuario es un miembro de ese grupo. E. g. el plugdev o disk grupos

  2. 20

    Si usted necesita privilegios de root cada vez, lo mejor es iniciar el programa como root y soltar (en un subproceso) con setuid y setgid. Eso es lo que apache no cuando se necesita unirse a las restricciones del puerto 80.

    Si obtener permisos de root es la excepción en lugar de la regla y el programa se ejecute de forma interactiva, de otra forma es escribir un programa add_interface y ejecutar

    sudo add_interface args

    y dejar sudo gestionar la autenticación para usted. En vez de sudo, puede que desee utilizar una interfaz gráfica como gksu, gksudo, kdesu, o kdesudo. Yo no intentar poner en práctica segura la contraseña de entrada a mí mismo; puede ser un problema difícil y probablemente vas a dejar boquiabierto agujeros de seguridad y problemas de funcionalidad (¿son compatibles los lectores de huellas digitales?).

    Otra alternativa es polkit, anteriormente llamado PolicyKit.

    • Aaaah, sólo he publicado mi respuesta y este se acercó – este es un buen consejo. +1.
    • +1 para PolicyKit.
  3. 7

    Usted no puede obtener privilegios de root, usted debe comenzar a salir con ellos y reducir sus privilegios como sea necesario. La forma habitual de hacerlo es instalar el programa con el «setuid» conjunto de bits: este ejecuta el programa con el id de usuario del propietario del archivo. Si ejecuta ls -l en sudo, verás que está instalado de esa manera:

    -rwsr-xr-x 2 root root 123504 2010-02-25 18:22 /usr/bin/sudo

    Mientras el programa se está ejecutando con privilegios de root, puede llamar a la setuid(2) llamada al sistema para cambiar su id de usuario efectivo a algunos de usuario no privilegiado. Creo (pero no lo he probado) que usted puede instalar el programa como root con el bit setuid activado, reducir inmediatamente privilegio y, a continuación, restaurar los privilegios como sea necesario (es posible, sin embargo, que una vez que se baja el privilegio de que usted no será capaz de restaurar).

    La mejor solución es romper el pedazo de programa que debe ejecutarse como root, e instalar con el bit setuid activado. Usted, por supuesto, deben tomar las precauciones razonables que no puede ser invocada fuera de su programa de máster.

    • Gracias ! Parece que este es el camino a seguir, de hecho. Voy a probar y dar los resultados de la espalda 😉
  4. 4

    Normalmente esto se realiza a través de su binarios suid root.

    Una forma de gestión de este modo que los ataques en contra de su programa duro es minimizar el código que se ejecuta como root, así:

    int privileged_server(int argc, char **argv);
    int unprivileged_client(int argc, char **argv, int comlink);
    
    
    int main(int argc, char **argv) {
        int sockets[2];
        pid_t child;
        socketpair(AF_INET, SOCK_STREAM, 0);  /* or is it AF_UNIX? */
    
        child = fork();
        if (child < 0) {
            perror("fork");
            exit(3);
        } elseif (child == 0) {
            close(sockets[0]);
            dup2(sockets[1], 0);
            close(sockets[1]);
            dup2(0, 1);
            dup2(0, 2); /* or not */
            _exit(privileged_server(argc, argv));
        } else {
            close(sockets[1]);
            int rtn;
            setuid(getuid());
            rtn = unprivileged_client(argc, argv, sockets[0]);
            wait(child);
            return rtn;
        }
    }

    Ahora los privilegios del código habla con el privilegio de código a través de la fd comlink (que es un socket conectado). El correspondiente código privilegiado que se utiliza la entrada estándar stdin/stdout como a su fin de la comlink.

    El código privilegiado que se necesita para comprobar la seguridad de cada una de las operaciones que tiene que hacer, pero como este código es pequeño en comparación con los privilegios del código este debe ser razonablemente fácil.

    • el segundo bloque creo que te refieres child > 0
    • En realidad, yo creo que debe ser else if (child == 0) — el else bloque wait s para el niño, por lo que el niño necesita para ser el medio else if bloque.
    • user470379 es correcta. Fijo.
    • Usted probablemente querrá AF_UNIX si desea pasar descriptores de archivo a través del socket.
    • Yo deliberadamente diseño para que no me pase de descriptores de archivo a su alrededor.
  5. 2

    Es posible que desee echar un vistazo a estas Api:

    setuid, seteuid, setgid, setegid, ...

    Están definidos en el encabezado de <unistd.h> en los sistemas Linux (no sé mucho acerca de MAC, pero usted debe tener un encabezado similar no demasiado).

    Un problema que puedo ver es que el proceso debe tener privilegios suficientes para cambiar su usuario/grupo – IDs. De lo contrario, las llamadas a las funciones anteriores, se producirá un error con errorno conjunto para EPERM.

    Yo sugeriría que ejecutar el programa como el root de usuario, cambiar el IDENTIFICADOR de usuario efectivo (utilizando seteuid) a un desfavorecidos de usuario en el principio. Entonces, cada vez que usted necesita para elevar los permisos, que se pida una contraseña, a continuación, utilizar seteuid de nuevo para volver a la root usuario.

  6. 2

    En OS X, puede utilizar el AuthorizationExecuteWithPrivileges función. La página en Servicios De Autorización De Tareas tiene algunos elaborar la discusión de este (y relacionados) funciones.

    He aquí un poco de C++ de código para ejecutar un programa con privilegios de administrador:

    static bool execute(const std::string &program, const std::vector<std::string> &arguments)
    {
        AuthorizationRef ref;
        if (AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &ref) != errAuthorizationSuccess) {
            return false;
        }
    
        AuthorizationItem item = {
            kAuthorizationRightExecute, 0, 0, 0
        };
        AuthorizationRights rights = { 1, &item };
        const AuthorizationFlags flags = kAuthorizationFlagDefaults
                                       | kAuthorizationFlagInteractionAllowed
                                       | kAuthorizationFlagPreAuthorize
                                       | kAuthorizationFlagExtendRights;
    
        if (AuthorizationCopyRights(ref, &rights, kAuthorizationEmptyEnvironment, flags, 0) != errAuthorizationSuccess) {
            AuthorizationFree(ref, kAuthorizationFlagDestroyRights);
            return false;
        }
    
        std::vector<char*> args;
        for (std::vector<std::string>::const_iterator it = arguments.begin(); it != arguments.end(); ++it) {
            args.push_back(it->c_str());
        }
        args.push_back(0);
    
        OSStatus status = AuthorizationExecuteWithPrivileges(ref, program.c_str(), kAuthorizationFlagDefaults, &args[0], 0);
    
        AuthorizationFree(ref, kAuthorizationFlagDestroyRights);
        return status == errAuthorizationSuccess;
    }
    • Donde llamamos a esta función? Y ¿cuáles serían los argumentos parámetro? Traté de llamar al comienzo de la función principal, pero se estrelló. los argumentos eran nulos. Mi problema es crear un archivo en /var/log. Pero, es necesario el permiso. ¿Cómo puedo lidiar con este problema?
    • Sería digno de mencionar todas las bibliotecas de este código necesita, ¿no?
  7. 0

    Puede intentar lanzar el comando para crear el dispositivo virtual (incluyendo sudo) a través de un fondo de shell. Pide las contraseñas de los usuarios en un cuadro de diálogo de la propia y de la tubería que en el shell cuando sudo pide. Hay otras soluciones como el uso de gksu, pero esos no están garantizados para estar disponible en cada máquina.

    No ejecutar todo el programa como root, pero sólo la pequeña parte de lo que necesita root. Se debe generar un proceso independiente para que y sudo puede ser de ayuda para usted.

    • Gracias por tu respuesta. Desafortunadamente, el programa no siempre se necesita privilegios de root. A veces, es posible que sólo quieren utilizar de una manera por lo que no necesita para realizar esa tarea en particular. En tal caso, pidiendo la contraseña no es necesaria. He encontrado hilos que hablan de setuid(). Voy a investigar esto.
    • Es sudo garantiza que esté disponible en cada máquina? He visto las instalaciones sin ella.
    • Nope, no es configurado en fedora por defecto. Yo también personalmente a bloquear a los usuarios y no en el grupo wheel de usar sudo o su como una extensión de unix tradicional comportamiento.
    • Sólo se ejecuta la parte del código que necesita root privs a través de sudo de curso. Cuando usted no necesita root privs, no pida la contraseña. Ejecuta el programa completo a través de sudo NO era mi respuesta, ‘el comando’ se refiere SÓLO a los comandos que necesita root privs, no toda la aplicación.
    • No el Ubuntu Software Center de forma interactiva obtener privilegios de root durante la operación? Al parecer, a través de polkit.

Dejar respuesta

Please enter your comment!
Please enter your name here