프로세스 권한 삭제


12

루트로 실행되는 데몬에 의해 시작되는 프로세스가 있습니다. 이제이 프로세스의 권한을 일반 사용자의 권한으로 "다운 그레이드"하고 싶습니다. 이게 가능해? 그렇다면 어떻게합니까?

PS : 맥에서 유닉스 운영하기

답변:


5

프로세스 자체는 setuid (2)를 호출해야합니다. 아직 chroot (8)에서 실행하지 않는지 조사해야합니다. 내가 아는 한 루트가 다른 프로세스의 uid를 변경할 수있는 방법이 없습니다.

루트로 실행하는 이유는 포트를 바인딩하는 것이므로 상위 포트에서 일반 사용자로 실행하고 OS X에서 ipfw (8)를 사용하여 포트 80 / 443 / etc를 상위 포트로 전달하는 것이 좋습니다.

http://support.crashplanpro.com/doku.php/recipe/forward_port_443_to_pro_server_on_mac_osx


루트로 실행되는 프로그램에 setuid (uid)를 넣었지만 일반 사용자로 실행하려면 아무 것도 필요하지 않습니다. 즉 루트로 계속 실행됩니다.
Samantha Catania

아마 그 시점에서 오류를 잡아야 할 것입니다 (어쩌면 uid에 대한 EINVAL을 얻고있을 것입니다). 아파치가 _www로 실행 중인지 확인하면 시스템에서 setuid가 깨질 가능성이 없습니다. 프로그래머 문서 : developer.apple.com/library/mac/#documentation/Darwin/Reference/…
다항식

그것이 맞더라도 uid에서 구문 오류가 발생하는 것이 맞습니다. 이것이 올바른 형식 setuid (500)입니까?
사만다 카타니아

문제를 발견했습니다 : system ()을 통해 명령을 실행하려고했지만 명령을 실행하면 문제가 해결되었습니다. 도움을위한 thx
Samantha Catania

아닙니다. 이것은 좋은 조언이 아닙니다. setuid()혼자 부르는 것만으로는 충분하지 않습니다.
니콜라스 윌슨

13

sudo tcpdump -Z initgroups (3), setgid (2) 및 setuid (2)를 사용하여 자체 프로세스의 루트 권한을 삭제합니다.

# code taken from: 
# http://www.opensource.apple.com/source/tcpdump/tcpdump-32/tcpdump/tcpdump.c

/* Drop root privileges and chroot if necessary */
static void
droproot(const char *username, const char *chroot_dir)
{
...
            if (initgroups(pw->pw_name, pw->pw_gid) != 0 ||
               setgid(pw->pw_gid) != 0 || setuid(pw->pw_uid) != 0) {
                    fprintf(stderr, "tcpdump: Couldn't change to '%.32s' uid=%lu gid=%lu: %s\n",
                        username, 
                        (unsigned long)pw->pw_uid,
                        (unsigned long)pw->pw_gid,
                        pcap_strerror(errno));
                    exit(1);
            }
...
}

2
옳은. initgroups, setgid, setuid(마지막!)를 정확하게 유닉스의 오른쪽 패러다임, 항상 따라야한다. 또한 책임있는 "droproot"함수는 세 가지 기본 함수가 모두 성공을 반환하더라도 uid 및 gid가 실제로 설정되어 있는지 확인합니다.
니콜라스 윌슨

3

다음을 사용하여 다른 사용자로 명령을 실행할 수 있습니다 su.

 su USERNAME -c COMMAND

COMMAND삭제 된 권한으로 실행 됩니다 USER.


기본적으로 su대상 사용자의 쉘 ​​인터프리터를 사용하여 명령을 실행합니다. 반대로 기본 동작은 현재 환경에서 실행되는 독립형 프로그램으로 sudo취급하는 COMMAND것입니다. 물론 이러한 기본 동작은 다양한 스위치 및 환경 변수를 사용하여 변경할 수 있습니다.


같은 외모는 suUSERNAME가 정의 된 쉘이없는 (또는 경우 작동하지 않습니다 /bin/false) sudo는이 작업을 수행하는 반면.
Aif

1
@Aif 사용자가 대화 형 명령을 실행할 수없는 경우 기본 동작에 해당 내용 su이 반영됩니다. 그러나 항상 -s스위치 를 사용하여이를 무시할 수 있습니다 . 목적은 su주어진 사용자의 행동을 모방하는 것입니다. 이는 보통 자신의 껍질에 의해 영향을받습니다. 반대로, sudo기본적으로 대상 사용자의 쉘 ​​설정은 무시합니다.
rozcietrzewiacz

아니요, 단순히 권한을 삭제하기 위해 쉘을 사용하여 작업을 실행하지 마십시오. 따라서 공격자가 제어 할 수없는 많은 구성 파일을 읽을 수 있습니다.
니콜라스 윌슨

2

권한을 삭제하려면 비 루트 사용자가 필요합니다. 그런 다음 해당 사용자로 전환하면됩니다.

#define UNPRIV_UID  48
#define UNPRIV_GID  48

if (getuid() == 0) { // we are root
    // setting UID/GID requires root privileges, so if you don't set
    // the GID first, you won't be able to do it at all.
    if (setgid(UNPRIV_GID)!=0) die("Failed to set nonroot GID");
    if (setuid(UNPRIV_UID)!=0) die("Failed to set nonroot UID");
}

ASSERT(getuid() != 0); 

이는 랩퍼 스크립트가 아닌 프로그램 자체에서 수행 됩니다 . 많은 프로그램은 특정 목적 (예 : 낮은 번호의 포트에 바인딩)을 위해 루트 권한이 필요하지만 그 이후에는 루트가 필요하지 않습니다. 따라서 이러한 프로그램은 루트로 시작되지만 더 이상 필요하지 않으면 권한을 삭제합니다.

루트 권한이 전혀 필요하지 않으면 루트 권한으로 실행하지 마십시오. 예 :

# Change this:
myprog -C /my/config/file

# To this:
sudo -u someuser myprog -C /my/config/file
# Or this
su someuser -c "myprog -C /my/config/file"

1
이를 통해 프로세스가 원하는 경우 권한을 복구 할 수 있습니다. 이 setuid함수 는 실제 UID가 아닌 유효 UID 만 설정합니다 . setreuid프로세스가 권한을 다시 얻지 못하도록 하려면 사용해야 합니다. (그리고 위의 코드는 보조 그룹 권한으로 취급하지 않습니다 중 하나 그것은 단지 대부분 신뢰할 수있는 코드를 실행하기에 적합합니다..)
데이비드 슈워츠

@David Schwartz 코드는 사용 된 메커니즘을 보여주기 위해 의도적으로 단순화되었습니다.
tylerl

보안이 중요한 코드를 단순화하려면 이것이 현재 하고있는 일임을 분명히해야합니다. 그리고 그렇지 않을 때는 "단지 문제"와 같은 것을 말해야합니다.
David Schwartz

2
@David 실제로, setuid()실제 사용자 ID와 저장된 사용자 ID를 설정합니다. 당신은 생각할 수 있습니다 seteuid(). 모든 시스템에이있는 setreuid()것은 아니므로 어느 곳에서나 사용할 수 없습니다. 정확한 의미 setuid()는 복잡하지만 euid 0이 있으면 모든 기존 사용자 ID 권한을로 삭제할 수 있습니다 setuid(). 이 대답에서 가장 큰 누락이 있다는 것이다 initgroupssetgroups뿐만 아니라 호출해야 setgid하고 setuid, 그보다 철저한 주장이 마지막에 수행해야합니다.
니콜라스 윌슨

0

다른 실행 파일을 실행하는 중입니다. 즉, 호출하는 기능 execve이나 다른 exec기능을 사용하는 경우 ( system또는 같은 기능을 통해 간접적으로) popen자식 프로세스를 처음부터 권한없이 실행해야하는 경우 가장 간단한 방법은 셸을 호출하고을 호출하십시오 su. 다음은 Perl에서 코드가 어떻게 생겼는지에 대한 개요입니다.

$shell_command = quotemeta($path_to_executable) . " --option";
$shell_command =~ s/'/'\\''/; # protect single quotes for the use as argument to su
$su_command = sprintf("su -c '%s' %s", $shell_command, quotemeta($user_name));
open(PIPE, "$su_command |") or die;

자식 프로세스가 루트로 시작해야하지만 나중에 권한을 삭제해야하는 경우 프로세스의 권한 을 다운 그레이드하는 방법을 보여주는 이 답변의 코드를 참조하십시오 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.