Ubuntu에서 명령 ID가 다른 실제 UID와 유효한 UID를 인쇄하도록 만드는 방법

Ubuntu에서 명령 ID가 다른 실제 UID와 유효한 UID를 인쇄하도록 만드는 방법

명령의 정보 페이지에는 id실제 사용자 ID와 다른 경우 유효한 사용자 ID를 출력한다고 명시되어 있습니다. 저는 우분투에서 일반(권한이 없는) 사용자로 Bash 셸을 사용하여 명령을 실행하여 어떻게든 이를 달성하려고 노력해 왔습니다. 예를 들어 @Asain Kujovic의 답변에서 예제를 시도했습니다.여기하지만 작동하지 않고 아무런 출력도 얻지 못합니다 euid. 예는 다음과 같습니다.

osbo@osboxes:~/t$ sudo gcc -o test.bin -xc - <<EOF
     #include <stdlib.h>
     #include <unistd.h>
     int main() { seteuid(0); system("id"); }
EOF
osbo@osboxes:~/t$ sudo chmod +s test.bin && ./test.bin && sudo rm test.bin
uid=1000(osbo) gid=1000(osboxes) groups=1000(osboxes),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),109(netdev),113(bluetooth),119(scanner)

편집하다:
저는 Linux 초보자이므로 제가 묻는 질문에 대해 이것이 가능하다면 초보자 친화적인 답변을 환영합니다. 나는 쉘 프로그램이 무엇인지(예: Bash 또는 sh), 환경 변수가 무엇인지, C 프로그램이 무엇인지, 시스템 호출이 무엇인지(예: getuid및 ) 알고 있습니다 geteuid. 또한 사용자 생성 프로세스와 관련된 실제 유효하고 저장된 사용자/그룹 ID가 무엇인지도 알고 있습니다. 그러나 부모-자식 프로세스 시나리오나 strace명령에 대해서는 아는 바가 거의 없습니다.

답변1

system("code")실제로는 , , , sh 매개변수를 사용하여 실행 됩니다.sh-c--code1 자식 프로세스에서. 보안 조치로서 일부 셸은 다음과 같은 기능을 수행합니다.

if (geteuid() != (uid = getuid())
  setuid(uid);

즉, 유효 uid가 실제 uid와 다를 경우 유효 uid를 실제 uid로 복원합니다.

setuid 실행 파일을 작성할 때(가능하면 처음부터 수행하지 않아야 함), 권한 상승 취약점이 발생하지 않도록 상승된 권한으로 실행되는 코드 부분이 가능한 한 짧고 엄격하게 제어되도록 해야 합니다.

보안 쉘 스크립트를 작성하는 것은 거의 불가능하기 때문에 setuid 실행 파일에서 쉘을 실행하는 것은 가장 원하지 않는 작업입니다. 따라서 이러한 쉘은 시작 시 초기에 이러한 권한을 제거함으로써 이를 달성하는 데 도움이 되며, 이는 자체적으로는 수행할 수 없는 잘못된 setuid 명령 작성을 용이하게 합니다.

다음은 대시 기반 Ubuntu 시스템의 zsh에서 가져온 것입니다.

$ sudo install -m 4750 -o root -g "$GID" =env .
$ ls -ld env
-rwsr-x--- 1 root stephane 43352 Dec  7 16:12 env*
$ sudo strace -u "$USERNAME" -ze '/uid|execve' ./env sh -c ''
execve("./env", ["./env", "sh", "-c", ""], 0x7ffde6ddf108 /* 17 vars */) = 0
execve("/usr/bin/sh", ["sh", "-c", ""], 0x7fff075efcd0 /* 17 vars */) = 0
getuid()                                = 10031
geteuid()                               = 0
geteuid()                               = 0
setuid(10031)                           = 0
geteuid()                               = 10031
+++ exited with 0 +++

이를 수행하는 일부 쉘에는 일반적으로 -p이를 비활성화하는 옵션이 있지만 이것이 사용 중입니다 system(). 그러면 그들은 자신의 권한을 포기하지 않지만 여전히 자신의 환경을 너무 많이 신뢰하지 않도록 더 조심합니다.

$ sudo strace -u "$USERNAME" -ze '/uid|execve' ./env sh -pc ''
execve("./env", ["./env", "sh", "-pc", ""], 0x7ffd4616dfb8 /* 17 vars */) = 0
execve("/usr/bin/sh", ["sh", "-pc", ""], 0x7ffef3883230 /* 17 vars */) = 0
getuid()                                = 10031
geteuid()                               = 0
+++ exited with 0 +++

여기서 할 수 있는 일은 실제 uid와 유효 uid가 모두 0이 되도록 setuid(0)호출하기 전에 수행하는 것 입니다. 그러나 이는 쉘이 권한을 포기하지 않고 해당 환경을 신뢰하지 않는다는 것을 의미합니다. system()그래서 이것은 매우 나쁜 생각입니다. 적어도 sudosetuid 실행 파일에서 as를 호출하기 sh전에 setuid와 같은 명령으로 수행된 모든 정리 작업을 수행하고 싶을 것입니다 root.

예를 들어 zsh여기서는 삭제 작업을 수행하지 않고 다음 작업을 수행하기 위해 내장 uid 변경을 지원합니다 setuid().

$ sudo strace -u "$USERNAME" -ze '/uid|execve' ./env zsh -c 'UID=0; exec "$@"' zsh sh -c 'id -u'
execve("./env", ["./env", "zsh", "-c", "UID=0; exec \"$@\"", "zsh", "sh", "-c", "id -u"], 0x7ffc6de6e5e8 /* 17 vars */) = 0
execve("/usr/bin/zsh", ["zsh", "-c", "UID=0; exec \"$@\"", "zsh", "sh", "-c", "id -u"], 0x7ffda351af70 /* 17 vars */) = 0
getuid()                                = 10031
geteuid()                               = 0
getuid()                                = 10031
setuid(0)                               = 0
execve("/usr/bin/sh", ["sh", "-c", "id -u"], 0x562a89149d20 /* 21 vars */) = 0
getuid()                                = 0
geteuid()                               = 0
geteuid()                               = 0
0
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=47576, si_uid=0, si_status=0, si_utime=0, si_stime=0} ---
+++ exited with 0 +++

자식 프로세스의 setuid 실행 파일에서 별도의 실행 파일을 실행해야 하는 경우 적절한 system()작업(자식 프로세스에서 포크, 실행, 일부 신호 차단 및 부모 프로세스에서 대기)을 수행할 수 있지만 최소한 Over 는 건너뜁니다 sh. 조회에 의존하기보다는 실행 파일에 대한 전체 경로를 제공하려고 하며 $PATH일부 환경 정리를 수행해야 할 수도 있습니다.


1 실제로 일반적으로 , , 로 사용됩니다 sh.-ccode이는 현대적인 구현을 의미합니다 sh.code-또는 로 시작하십시오 +. 이제 더 많은 구현 변경이 있을 수 있습니다.POSIX 시행표준 8판 이후.

관련 정보