c++ 프로그래밍 방식으로 루트 권한을 얻는 방법?



root elevated-privileges (5)

나는 권한이없는 사용자로 실행되지만 어떤 시점에서 (새로운 가상 장치를 생성하기 위해) 루트 권한이 필요한 소프트웨어 (Linux / Mac OSX 용 C ++)를 작성 중이다.

이 프로그램을 루트로 실행하는 것은 (주로 보안 문제 때문에) 옵션이 아니며 "실제"사용자의 ID (uid)를 알아야합니다.

임시로 루트 권한을 얻고 특정 작업을 수행하는 "sudo"명령 동작 (사용자 암호 요청)을 모방하는 방법이 있습니까? 그렇다면 어떤 기능을 사용할 수 있습니까?

당신의 도움을 주셔서 대단히 감사합니다 !

https://ffff65535.com


OS X에서는 AuthorizationExecuteWithPrivileges 함수를 사용할 수 있습니다. Authorization Services Tasks 의 페이지에는이 (및 관련) 기능에 대한 정교한 토론이 있습니다.

다음은 관리자 권한을 가진 프로그램을 실행하기위한 약간의 C ++ 코드입니다.

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;
}

다음 API를 살펴 보시기 바랍니다.

setuid, seteuid, setgid, setegid, ...

그것들은 리눅스 시스템의 헤더 ( <unistd.h> 에 정의되어 있습니다 (MAC에 대해 많이 알지 못하지만 비슷한 헤더가 있어야합니다).

내가 볼 수있는 한 가지 문제점은 프로세스가 사용자 / 그룹 ID를 변경할 수있는 충분한 권한을 가져야한다는 것입니다. 그렇지 않으면 위의 함수를 호출하면 errornoEPERM 설정된 오류가 발생합니다.

root 사용자로 프로그램을 실행하고, seteuid 사용하여 유효 사용자 ID를 초창기에 불우한 사용자로 변경하는 것이 좋습니다. 그런 다음 권한을 늘려야 할 때마다 암호를 묻는 메시지를 표시 한 다음 seteuid 다시 사용하여 root 사용자로 되돌립니다.


매번 루트 권한이 필요하다면 가장 좋은 방법은 root로 프로그램을 시작하고 setuidsetgid 사용하여 (하위 프로세스에서) 프로그램을 삭제하는 것입니다. 이것이 제한된 포트 80에 바인딩해야 할 때 아파치가 수행하는 작업입니다.

루트 권한을 얻는 것이 규칙 대신 예외이고 프로그램이 대화식으로 실행되는 경우 다른 방법은 add_interface 프로그램을 작성하고

sudo add_interface args

그리고 sudo가 당신을 위해 인증을 처리하게하십시오. sudo 대신 gksu, gksudo, kdesu 또는 kdesudo와 같은 그래픽 프론트 엔드를 사용할 수 있습니다. 나는 안전한 암호 입력을 직접 구현하려고하지 않을 것이다. 까다로운 문제 일 수 있으며 보안 문제와 기능상의 문제 (지문 판독기를 지원합니까?)가 크게 달라질 수 있습니다.

또 다른 대안은 이전에 PolicyKit이라고 불리는 polkit 입니다.


백그라운드 셸을 통해 가상 장치 (sudo 포함)를 만드는 명령을 실행해볼 수 있습니다. 자신의 대화창에서 사용자 암호를 물어보고 sudo가 암호를 묻는 메시지를 쉘에 입력하십시오. gksu 사용과 같은 다른 솔루션이 있지만 모든 컴퓨터에서 사용할 수있는 것은 아닙니다.

전체 프로그램을 루트로 실행하지 않고 루트가 필요한 작은 부분 만 실행합니다. 별도의 프로세스를 생성해야하며 sudo가 도움이 될 수 있습니다.


원문 답변

실행 파일 자체에서 setuid 스위치를 고려할 수 있습니다. Wikipedia에는 geteuid()getuid() 사이의 차이점을 아주 효과적으로 보여주는 article 가 있습니다. 전자는 "누구를"에뮬레이션하고있는 사람인지 "누구인지"에 대한 후자를 찾는 것입니다. sudo 프로세스 (예 : geteuid)는 0 (root)을 반환하고 사용자 ID는 getuid하지만 sudo id -u -r 사용하면 하위 프로세스가 실제로 root로 실행됩니다.

루트 권한을 쉽게 프로그래밍 방식으로 얻을 수있는 방법이 없다고 생각합니다. 결국 최소 권한 원칙을 적용하면 왜 필요합니까? 일반적으로 높은 수준의 권한으로 코드의 일부만 실행하는 것이 일반적입니다. 대부분의 데몬은 현대 시스템에서 필요한 권한 대부분을 자신의 사용자로 실행하도록 설정됩니다. 루트 권한이 정말로 필요하다는 것은 아주 구체적인 작업 (마운트 등)에만 해당됩니다.

2013 년 업데이트

내 원래 답변은 나와 있습니다 (내 2013 자체는 내 2010보다 나은 작업 일지 모르지만). 루트 액세스가 필요한 응용 프로그램을 디자인하는 경우 정확히 어떤 종류의 루트 액세스가 필요한지 고려하고 POSIX 기능 사용 (맨 페이지) . 이는 L4 외에서 구현 된 능력 기반 보안 과는 다르다. POSIX 기능을 사용하면 응용 프로그램에 루트 권한의 하위 집합을 부여 할 수 있습니다. 예를 들어 CAP_SYS_MODULE 을 사용하면 커널 모듈을 삽입 할 수 있지만 다른 루트 권한은 없습니다. Fedora에는 무차별 루트 액세스로 setuid 바이너리를 완전히 제거하는 기능이 있습니다.

이것은 프로그래머로서 코드가 분명 완벽하기 때문에 중요합니다! 그러나, 당신이 의존하는 도서관 (한숨 만 쓰면, 한숨을 쉬었다!)에 취약점이있을 수있다. 기능을 사용하면이 익스플로잇의 사용을 제한하고 자신과 귀사를 보안 관련 조사에서 제외 할 수 있습니다. 이것은 모든 사람을 더 행복하게 만듭니다.





elevated-privileges