Set-uid 실행 파일 및 생성된 프로세스 사용자

Set-uid 실행 파일 및 생성된 프로세스 사용자

Ubuntu 14.04에서 passwd실행 파일은 다음과 같습니다.

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

실행 파일 ping

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

따라서 (둘 다) 실행 중인 프로세스의 uid는 root일반 사용자가 실행하더라도 result 여야 합니다. passwd에서 실행 하면 user1실제로 다음을 얻습니다.

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

하지만 탈출하면 ping다릅니다 user1.

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

root첫 번째 경우에는 프로세스의 uid가 0으로 설정되고 두 번째 경우에는 0으로 설정되지 않는 이유는 무엇입니까 ?

답변1

@rui-f-ribeiro 발언의 일반적인 의미는 맞지만, 세부적인 내용은 그렇지 않습니다. 세부 사항이 중요합니다. Ubuntu는 다음 패키지를 사용합니다.

limit_capabilitiesping 유틸리티는 ping 및 ping6이 공유하는 함수에서 권한을 재설정합니다 . 관련 코드 블록은 다음과 같습니다.

        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

즉, (소스 코드 읽기) ping여러 권한 있는 작업을 수행하고 권한을 포기하지만 개인 취향에 따라 다른 방식으로 실행되도록 구축할 수 있습니다.

흥미롭게도 변경 로그에는 다음과 같이 명시되어 있습니다.

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.

이야기는 passwd비슷하지만 세부 사항은 다릅니다. 그것은그림자툴킷에서는 다음 권한이 제거될 수 있습니다 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);
    }

하지만 이는 특별한 경우에만 수행됩니다.

/*
 * 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
 */

일반적인 경우에는 권한이 있는지 확인하고 이를 제거하지 않습니다(권한이 필요하지 않은 다른 작업은 없기 때문에).

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

대부분의 유틸리티는 이러한 권한이 설치되어 있지 않다는 가정 하에 setuid/setgid 동작을 재설정하지 않습니다.

답변2

@schily가 말했듯이 ping 유틸리티(및 기타 유틸리티)에서 루트 권한은 더 이상 필요하지 않으면 제거됩니다. 이는 보안상의 이유로 수행됩니다.

ping.c - main()에서 getuid 및 setuid 호출을 통해 사용자 루트를 제거합니다.

getuid()는 현재 사용자를 가져오고 루트로 setuid()를 실행하면 프로세스의 uid가 변경됩니다.

/*
 * 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

답변3

소켓을 연 후 루트가 더 이상 필요하지 않으므로 두 번째 프로세스의 uid가 재설정되었습니다.

확인할 때 passwd유틸리티에는 여전히 루트 권한이 필요합니다.

이를 확인하려면 소스 코드를 확인해야 합니다. uid 재설정이 너무 빨리 완료되어 재설정하기 전에 다른 사람이 uid를 확인할 수 있는 기회를 제공할 수 있기 때문입니다.

관련 정보