나는 setuid
이것이 어떻게 작동하는지 이해하려고 노력하고 있습니다.
그래서 현재 사용자만 인쇄하는 더미 프로그램을 만들었습니다.
#include<bits/stdc++.h>
using namespace std;
int main(){
cout << system("id -a") << "\n";
cout << system("whoami") << "\n";
}
my-binary
user 아래에 실행 파일을 컴파일하고 생성했습니다 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/sh
bash
dash
mksh
-p
Bash 매뉴얼 페이지는 다음과 같이 말합니다.
쉘 시작 시 유효 사용자(그룹) ID가 실제 사용자(그룹) ID와 동일하지 않고 옵션이 다음
-p
과 같은 경우사용 불가[...] 유효 사용자 ID는 실제 사용자 ID로 설정됩니다.
dash
( /bin/sh
Debian/Ubuntu에서) 이것은 다음과 같습니다 .조금 새로운: 아직 Debian 9 Stretch(2017)에서는 그렇지 않습니다. 단지 데비안에만 해당됩니다.변화, 아직 업스트림이 아님원천2020년 2월 4일 현재. bash
이는 버전 2.X(RedHat 7.X, 2000에 처음 포함됨)부터 사용 가능했습니다.
이것은아직은 그렇지 않다다른 쉘( ksh93
등 zsh
) 또는 /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;
}