일반 사용자가 실행할 때 루트 권한이 필요한 프로세스가 있습니다. 분명히 "setuid 비트"를 사용하여 이 작업을 수행할 수 있습니다. POSIX 시스템에서 이를 수행하는 올바른 방법은 무엇입니까?
또한 인터프리터(bash, perl, python, php 등)를 사용하는 스크립트를 사용하여 이 작업을 어떻게 수행할 수 있나요?
답변1
이것사용자 ID 비트 설정실행 시 프로그램이 실제 사용자(다른 경우)가 아닌 파일 소유자의 권한을 갖도록 실행 파일에 설정할 수 있습니다. 그게 차이점이에요효과적인uid(사용자 ID) 및진짜uid.
일부 공통 유틸리티(예: passwd
)는 루트가 소유하고 필요에 따라 구성됩니다( 루트만 읽을 수 있는 권한 passwd
에 대한 액세스 필요 )./etc/shadow
이를 수행할 때 가장 좋은 전략은 슈퍼유저로서 필요한 작업을 즉시 수행한 다음 권한을 낮추어 루트로 실행할 때 오류나 오용이 발생할 가능성을 줄이는 것입니다. 이렇게 하려면 프로세스의 설정이 필요합니다.효과적인uid는 실제 uid입니다. POSIX C에서:
#define _POSIX_C_SOURCE 200112L // Needed with glibc (e.g., linux).
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
void report (uid_t real) {
printf (
"Real UID: %d Effective UID: %d\n",
real,
geteuid()
);
}
int main (void) {
uid_t real = getuid();
report(real);
seteuid(real);
report(real);
return 0;
}
POSIX 시스템에서 일반적으로 사용되는 관련 기능은 대부분의 고급 언어에서도 동일한 기능을 가져야 합니다.
getuid()
: 얻다진짜uid.geteuid()
: 얻다효과적인uid.seteuid()
:설정효과적인uid.
실제 uid와 일치하지 않는 마지막 항목으로는 아무것도 할 수 없습니다실행 파일에 setuid 비트가 설정되지 않은 경우. 따라서 이를 시도하려면 을 컴파일하십시오 gcc test.c -o testuid
. 그런 다음 권한이 있어야 합니다.
chown root testuid
chmod u+s testuid
마지막 것은 setuid 비트를 설정합니다. 이제 ./testuid
일반 사용자로 실행하면 프로세스가 기본적으로 유효 uid 0, 루트로 실행되는 것을 볼 수 있습니다.
스크립트는 어떻습니까?
이는 플랫폼에 따라 다릅니다., 그러나 Linux에서는 인터프리터(바이트 코드 포함)가 필요한 것들은 인터프리터에 설정되어 있지 않으면 setuid 비트를 사용할 수 없습니다(매우 어리석은 일입니다). 다음은 위의 C 코드를 모방한 간단한 Perl 스크립트입니다.
#!/usr/bin/perl
use strict;
use warnings FATAL => qw(all);
print "Real UID: $< Effective UID: $>\n";
$> = $<; # Not an ASCII art greedy face, but genuine perl...
print "Real UID: $< Effective UID: $>\n";
$>
*nixy 루트에 충실하게 Perl에는 유효 uid( ) 및 실제 uid( $<
) 에 대한 특수 변수가 내장되어 있습니다 . 그러나 동일한 작업을 시도 chown
하고 chmod
컴파일된 실행 파일(C, 이전 예제)과 함께 사용하면 아무런 차이가 없습니다. 스크립트가 권한을 얻을 수 없습니다.
대답은 setuid 바이너리를 사용하여 스크립트를 실행하는 것입니다.
#include <stdio.h>
#include <unistd.h>
int main (int argc, char *argv[]) {
if (argc < 2) {
puts("Path to perl script required.");
return 1;
}
const char *perl = "perl";
argv[0] = (char*)perl;
return execv("/usr/bin/perl", argv);
}
gcc --std=c99 whatever.c -o perlsuid
그런 다음 이것을 컴파일하십시오 chown root perlsuid && chmod u+s perlsuid
. 이제 실행할 수 있습니다어느유효 uid가 0인 Perl 스크립트,누가 그것을 소유하든 상관 없습니다.
비슷한 전략이 PHP, Python 등에 적용됩니다. 하지만...
# Think hard, very important:
>_< # Genuine ASCII art "Oh tish!" face
제발 제발이런걸 방치하지 마세요. 아마도 실제로는 스크립트 이름으로 컴파일하고 싶을 것입니다.절대 경로, 즉, 그 안의 모든 코드를 main()
다음으로 바꿉니다.
const char *args[] = { "perl", "/opt/suid_scripts/whatever.pl" }
return execv("/usr/bin/perl", (char * const*)args);
/opt/suid_scripts
루트가 아닌 사용자에 대해서는 그 안의 모든 내용이 읽기 전용 인지 확인합니다 . 그렇지 않으면 누군가가 그것을 위해 무엇이든 바꿀 수 있습니다 whatever.pl
.
또한 주의사항많은 스크립팅 언어에서는 환경 변수가 스크립트 실행 방식을 변경할 수 있도록 허용합니다.. 예를 들어 환경 변수로 인해 호출자가 제공한 라이브러리가 로드되어 호출자가 루트로 임의의 코드를 실행할 수 있습니다. 따라서 인터프리터와 스크립트 자체가 가능한 모든 환경 변수에 강력하다는 사실을 알지 못하는 한,이러지 마세요.
그래서 내가 무엇을해야하니?
루트가 아닌 사용자가 루트로 스크립트를 실행할 수 있도록 허용하는 보다 안전한 방법은 다음을 추가하는 것입니다.스도규칙을 만들고 사용자가 이를 실행하도록 합니다 sudo /path/to/script
. Sudo는 대부분의 환경 변수를 제거하고 관리자가 명령을 실행할 수 있는 사람과 매개변수를 세부적으로 선택할 수 있도록 해줍니다. 보다비밀번호를 묻지 않고 루트로 특정 프로그램을 어떻게 실행할 수 있나요?예를 들어.
답변2
응 그럴 수 있지만 그건 그렇지아마도 아주 나쁜 생각일 것이다.. 일반적으로 실행 파일에 SUID 비트를 직접 설정하지 않고 대신스도(8)또는수(1)시행(그리고 시행할 수 있는 사람을 제한)
그러나 일반 사용자가 루트로 프로그램(특히 스크립트!)을 실행하도록 허용하면 많은 보안 문제가 발생한다는 점에 유의하십시오. 대부분은 이 작업을 수행해야 하며, 이 문제를 처리하기 위해 프로그램이 구체적이고 매우 주의 깊게 작성되지 않는 한 악의적인 사용자가 이를 사용하여 루트 쉘을 쉽게 얻을 수 있습니다.
따라서 이 작업을 수행하더라도 환경, 명령줄 인수, STDIN 및 처리하는 모든 파일, 열리는 네트워크 연결의 데이터를 포함하여 루트로 실행하려는 프로그램에 대한 모든 입력을 먼저 정리하는 것이 좋습니다. , 등. . 이것은 하기 어려운 일이고, 올바르게 행하는 것은 더욱 어렵습니다.
예를 들어 사용자가 편집기만 사용하여 특정 파일을 편집하도록 허용할 수 있습니다. 그러나 편집기를 사용하면 외부 도우미에서 명령을 실행하거나 명령을 일시 중단하여 사용자가 원하는 대로 루트 셸 작업을 수행할 수 있습니다. 또는 완벽하게 안전해 보이는 셸 스크립트를 실행 중일 수 있지만 사용자는 수정된 $IFS 또는 기타 환경 변수를 사용하여 이를 실행하여 동작을 완전히 변경할 수 있습니다. 또는 "ls"를 실행하도록 되어 있는 PHP 스크립트일 수도 있지만 사용자가 수정된 $PATH를 사용하여 이를 실행하면 "ls"라는 이름의 셸이 실행됩니다. 또는 수십 가지 다른 보안 문제도 있습니다.
프로그램이 실제로 작업의 일부를 루트로 수행해야 하는 경우 일반 사용자로 실행되도록 수정하는 것이 더 좋지만 suid를 통해 절대적으로 루트가 필요한 부분만 (가능한 한 많이 정리한 후) 수행합니다. 돕는 사람.
모든 로컬 사용자를 완전히 신뢰하더라도(예: 루트 비밀번호 제공), 의도하지 않은 보안 감독(예: 온라인 PHP 스크립트 사용, 취약한 비밀번호 등)으로 인해 이는 좋지 않은 생각입니다. 방법)은 갑자기 원격 공격자가 전체 시스템을 완전히 손상시킬 수 있도록 허용합니다.
답변3
이 솔루션이 있습니다.
- shebang 라인과 함께 작동하도록 설계된 C 래퍼를 만듭니다. Setuid 루트.
- 일단 시작되면 래퍼는 인수로 제공된 스크립트가 setuid/setgid인지 확인합니다.
- 그렇지 않은 경우 루트 권한을 제거하십시오.
- 그렇다면 - setuid/setgid 비트를 반영하도록 유효 uid/gid를 변경합니다.
- 주어진 스크립트가 일반 파일인지 확인합니다. 그렇지 않으면 종료합니다.
- "perl -x script"를 통해 perl을 실행합니다.
보다 엄격하고 제한된 버전에서는 다음과 같은 작업을 수행할 수도 있습니다.
- setuid/setgid 루트 스크립트 실행을 비활성화합니다.
- 오염된 모드("perl -x -T 스크립트")에서 Perl을 실행합니다.
고급 버전에서는 sudo("exec sudo ... perl -x script")를 통해 Perl을 시작할 수 있습니다.