setuid가 작동하지 않습니다

setuid가 작동하지 않습니다

나는 setuid이것이 어떻게 작동하는지 이해하려고 노력하고 있습니다.

그래서 현재 사용자만 인쇄하는 더미 프로그램을 만들었습니다.

#include<bits/stdc++.h>
using namespace std;


int main(){
    cout << system("id -a") << "\n";
    cout << system("whoami")  << "\n";
}

my-binaryuser 아래에 실행 파일을 컴파일하고 생성했습니다 anmol.

-rwxrwxr-x 1 anmol anmol 9972 Feb  1 16:54 my-binary

그런 다음 setuid다음을 사용하여 옵션을 설정합니다 chmod +s.

-rwsrwsr-x 1 anmol anmol 9972 Feb  1 16:54 my-binary

정상적으로 실행하면 다음과 같은 결과가 나타납니다.

uid=1000(anmol) gid=1000(anmol) groups=1000(anmol),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),116(lpadmin),122(sambashare)
anmol

이제 다른 사용자로 변경을 사용 su user2하고 실행하면 다음과 같은 결과를 얻습니다.

uid=1001(user2) gid=1001(user2) groups=1001(user2)
user2

내가 그것을 sudo ./my-binary사용하여 실행할 때

uid=1001(root) gid=1001(root) groups=1001(root)
root

내가 이해한 바에 따르면, 어떻게 실행하더라도 매번 첫 번째 출력을 얻어야 하지 않나요?

여기에서 다른 유사한 질문을 확인했고 일부는 파일 시스템이 nosuid옵션으로 마운트되었는지 확인하라고 제안하여 실행 mount | /dev/sda1하고 출력을 얻었습니다.

/dev/sda1 on / type ext4 (rw,relatime,errors=remount-ro,data=ordered)

이는 옵션이 활성화되지 않았음을 의미합니다.

예상한 결과를 얻지 못하는 이유에 대한 힌트가 있습니까?

답변1

라이브러리 함수는 Linux에서 system(3)명령 인수 ( , 또는 ) 를 전달하여 실행 /bin/sh -c하며 이 옵션을 사용하여 호출 하지 않는 한 모든 setuid 또는 setgid 권한을 포기합니다 ./bin/shbashdashmksh-p

Bash 매뉴얼 페이지는 다음과 같이 말합니다.

쉘 시작 시 유효 사용자(그룹) ID가 실제 사용자(그룹) ID와 동일하지 않고 옵션이 다음 -p과 같은 경우사용 불가[...] 유효 사용자 ID는 실제 사용자 ID로 설정됩니다.

dash( /bin/shDebian/Ubuntu에서) 이것은 다음과 같습니다 .조금 새로운: 아직 Debian 9 Stretch(2017)에서는 그렇지 않습니다. 단지 데비안에만 해당됩니다.변화, 아직 업스트림이 아님원천2020년 2월 4일 현재. bash이는 버전 2.X(RedHat 7.X, 2000에 처음 포함됨)부터 사용 가능했습니다.

이것은아직은 그렇지 않다다른 쉘( ksh93zsh) 또는 /bin/sh다른 시스템(OpenBSD, FreeBSD, Solaris. 그러나 NetBSD는 아님)과 함께 사용변경됨bash처럼 작동합니다.)

가지고 있다면 특권 모드가 작동할 것입니다.다르게bash와 비교하면 다음과 같습니다.존재하다기본적으로 셸이 setuid 모드에서 실행 중일 때는 이를 켜야 합니다.떠나다set +p쉘이 setuid 권한을 제거하도록 합니다 .


를 사용하려면 setuid 바이너리에서 직접 셸 또는 실행 가능한 셸 스크립트를 실행한 system()다음 popen()"분할 성격"을 포기하고 다음을 통해 실제 또는 유효한 자격 증명으로 완전히 전환해야 합니다 setres[ug]id.

% cat a.cc
#include <unistd.h>
#include <stdlib.h>
int main(){
    uid_t euid = geteuid();
    setresuid(euid, euid, euid);
    system("id");
}
% c++ a.cc
% chmod u+s a.out
% ./a.out
uid=1002(fabe)
% su -c ./a.out
uid=1002(fabe)

바이너리가 실제로 유효한 자격 증명을 전환했는지 확인하려면 다음을 통해 외부 프로그램을 호출하는 대신 직접 수행하세요 system().

#include <iostream>
#include <unistd.h>
#include <pwd.h>
using namespace std;
int main(){
    uid_t euid = geteuid(); struct passwd *pw = getpwuid(euid);
    cout << "euid=" << euid;
    if(pw) cout << ", " << pw->pw_name;
    cout << endl;
}

관련 정보