나는 코드를 작성했습니다 :
// a.c
#include <stdlib.h>
int main () {
system("/bin/sh");
return 0;
}
다음 명령을 사용하여 컴파일합니다.
gcc a.c -o a.out
setuid 비트를 추가했습니다:
sudo chown root.root a.out
sudo chmod 4755 a.out
Ubuntu 14.04에서는 일반 사용자로 실행하면 루트 권한을 얻습니다.
하지만 Ubuntu 16.04에서는 여전히 현재 사용자의 쉘을 얻습니다.
왜 다른가요?
답변1
변경된 점은 /bin/sh
be bash
또는 stay bash의 동작을 모방하는 dash
추가 플래그가 있다는 것입니다 .-p
-p
Bash에서는 다음에 설명된 대로 setuid 권한을 포기하지 않기 위해 이 플래그가 필요합니다.매뉴얼 페이지:
쉘 시작 시 유효 사용자(그룹) ID가 실제 사용자(그룹) ID와 동일하지 않고 -p 옵션이 제공되지 않으면 시작 파일을 읽지 않으며 쉘 기능은 환경 및 SHELLOPTS, BASHOPTS, CDPATH 및 GLOBIGNORE 변수는 환경에 나타나면 무시됩니다.유효 사용자 ID를 실제 사용자 ID로 설정합니다.. 호출 시 -p 옵션을 제공하면 시작 동작은 동일하지만 유효 사용자 ID가 재설정되지 않습니다.
이전에는 dash
이것이 무시되었고 setuid 실행이 허용되었습니다(이를 방지하기 위한 조치가 취해지지 않았습니다). 하지만우분투 16.04 dash
맨페이지다음과 유사한 추가 옵션 설명이 있습니다 bash
.
-p priv
유효 uid가 uid와 일치하지 않으면 재설정을 시도하지 마십시오.잘못된 사용을 방지하기 위해 기본적으로 설정되어 있지 않습니다.system(3) 또는 popen(3)을 통한 Setuid 루트 프로그램.
이 옵션은 다음에는 존재하지 않습니다.상류(제안된 패치에 반응하지 않을 수 있습니다.*)도 Debian 9는 아니지만 2018년부터 패치된 Debian Buster에 있습니다.
"/bin/sh -p"
참고: Stéphane Chazelas가 설명했듯이 특정 콘텐츠가 실행되므로 system()
지금 전화하기에는 너무 늦었습니다. 따라서 setuid가 이미 삭제되었습니다.system()
/bin/sh
드 로버트이전 코드의 대답은 이 문제를 처리하는 방법을 설명합니다 system()
.
답변2
아마도 어떤 이유로 쉘은 시작 중에 유효 사용자 ID를 실제 사용자 ID로 다시 변경합니다. 다음을 추가하여 이를 확인할 수 있습니다.
/* needs _GNU_SOURCE; non-Linux users see setregid/setreuid instead */
uid_t euid = geteuid(), egid = getegid();
setresgid(egid, egid, egid);
setresuid(euid, euid, euid);
(실제로 Linux 에서도 system()
실제 항목을 설정해야 할 수 있습니다. 저장된 항목은 그대로 두어도 괜찮습니다. 이것은 단지 무차별 디버깅일 뿐입니다. ID를 설정한 이유에 따라 물론 필요할 수도 있습니다. 실제 ID를 어딘가에 저장하려면.)
[또한 이것이 setid 작동 방식을 배우는 연습 이상의 것이라면 특히 쉘을 호출할 때 걱정해야 할 보안 문제가 많이 있습니다. 예를 들어, 셸의 동작에 영향을 미치는 많은 환경 변수가 있습니다. sudo
가능하다면 기존 방법을 선호하세요. ]