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_capabilities
ping 유틸리티는 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를 확인할 수 있는 기회를 제공할 수 있기 때문입니다.