Executável do set-uid e usuário do processo resultante [duplicado]

10

No Ubuntu 14.04, o executável passwd é

-rwsr-xr-x 1 root root 47032 gen 27 01:50 /usr/bin/passwd

e o executável ping é

-rwsr-xr-x 1 root root 44168 mag  7  2014 /bin/ping

(para ambos) o uid do processo em execução deve resultar em root , mesmo quando eles são executados a partir de um usuário comum. Se eu executar passwd de user1 , de fato, obtenho

$ ps -aux | grep passwd
root      4317  0.0  0.0  85940  2004 pts/0    S+   10:24   0:00 passwd

mas se eu executar ping de user1 , não é o mesmo:

$ ps -aux | grep ping
user1    4362  0.0  0.0   6500   632 pts/0    S+   10:29   0:00 ping 192.168.8.1

Por que o uid do processo foi definido como root no primeiro caso e não no segundo?

    
por BowPark 10.05.2016 / 10:34

3 respostas

6

Como @schily diz, no utilitário ping (e outros), as permissões de root são descartadas depois que não são mais necessárias. Isso é feito por motivos de segurança.

De ping.c - main () - o usuário root é removido com a chamada getuid e setuid.

getuid () pega o usuário atual, e root fazendo um setuid () irá alterar o uid do processo.

/*
 * Pull this stuff up front so we can drop root if desired.
 */
if (!(proto = getprotobyname("icmp"))) {
    (void)fprintf(stderr, "ping: unknown protocol icmp.\n");
    exit(2);
}
if ((s = socket(AF_INET, SOCK_RAW, proto->p_proto)) < 0) {
    if (errno==EPERM) {
        fprintf(stderr, "ping: ping must run as root\n");
    }
    else perror("ping: socket");
    exit(2);
}

#ifdef SAFE_TO_DROP_ROOT    
    setuid(getuid());       /* HERE RETURNING TO THE USER */
#endif
    
por 10.05.2016 / 11:44
4

O uid do segundo processo já foi reiniciado porque não há mais necessidade de ser root depois que os soquetes forem abertos.

O utilitário passwd ainda precisa de privilégios de root ao ser verificado.

Se você quiser verificar isso, você precisará verificar o código-fonte, pois o reset do uid pode ser feito rápido demais para dar aos outros a chance de verificar o uid antes da reinicialização.

    
por 10.05.2016 / 10:55
4

O sentido geral da observação de @rui-f-ribeiro está correto, mas os detalhes não são. Detalhes são importantes. O Ubuntu usa esses pacotes:

O utilitário ping redefine as permissões em uma função chamada limit_capabilities , compartilhada por ping e ping6. O pedaço de código relevante se parece com isto:

        if (prctl(PR_SET_KEEPCAPS, 1) < 0) {
                perror("ping: prctl");
                exit(-1);
        }

        if (setuid(getuid()) < 0) {
                perror("setuid");
                exit(-1);
        }

        if (prctl(PR_SET_KEEPCAPS, 0) < 0) {
                perror("ping: prctl");
                exit(-1);
        }

        cap_free(cap_p);
        cap_free(cap_cur_p);
#endif
        uid = getuid();
        euid = geteuid();
#ifndef CAPABILITIES
        if (seteuid(uid)) {
                perror("ping: setuid");
                exit(-1);
        }
#endif

Isto é (leia o código fonte), ping realiza várias operações privilegiadas e descarta privilégios - mas pode ser construído para se comportar de diferentes maneiras de acordo com a preferência de cada um.

Curiosamente, as notas do changelog:

iputils (3:20121221-2) unstable; urgency=low

  * Enable the CAP_NET_RAW capability and strip the setuid bit on ping and
    ping6 binaries if possible.

A história de passwd é semelhante, com detalhes diferentes. Ele faz parte do conjunto de ferramentas shadow , que pode eliminar privilégios em change_root :

    /* Drop privileges */
    if (   (setregid (getgid (), getgid ()) != 0)
        || (setreuid (getuid (), getuid ()) != 0)) {
            fprintf (stderr, _("%s: failed to drop privileges (%s)\n"),
                     Prog, strerror (errno));
            exit (EXIT_FAILURE);
    }

Mas isso só acontece em um caso especial:

/*
 * process_root_flag - chroot if given the --root option
 *
 * This shall be called before accessing the passwd, group, shadow,
 * gshadow, useradd's default, login.defs files (non exhaustive list)
 * or authenticating the caller.
 *
 * The audit, syslog, or locale files shall be open before
 */

No caso normal, ele garante que tem privilégios e não os elimina (porque não há mais nada a fazer que não requeira o privilégio):

    if (setuid (0) != 0) {
            (void) fputs (_("Cannot change ID to root.\n"), stderr);
            SYSLOG ((LOG_ERR, "can't setuid(0)"));
            closelog ();
            exit (E_NOPERM);
    }

A maioria dos utilitários não redefine o comportamento setuid / setgid, presumindo que eles não estejam instalados com essas permissões.

    
por 10.05.2016 / 12:26