스크립트는 어떻습니까?

스크립트는 어떻습니까?

일반 사용자가 실행할 때 루트 권한이 필요한 프로세스가 있습니다. 분명히 "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

이 솔루션이 있습니다.

  1. shebang 라인과 함께 작동하도록 설계된 C 래퍼를 만듭니다. Setuid 루트.
  2. 일단 시작되면 래퍼는 인수로 제공된 스크립트가 setuid/setgid인지 확인합니다.
    • 그렇지 않은 경우 루트 권한을 제거하십시오.
    • 그렇다면 - setuid/setgid 비트를 반영하도록 유효 uid/gid를 변경합니다.
  3. 주어진 스크립트가 일반 파일인지 확인합니다. 그렇지 않으면 종료합니다.
  4. "perl -x script"를 통해 perl을 실행합니다.

보다 엄격하고 제한된 버전에서는 다음과 같은 작업을 수행할 수도 있습니다.

  • setuid/setgid 루트 스크립트 실행을 비활성화합니다.
  • 오염된 모드("perl -x -T 스크립트")에서 Perl을 실행합니다.

고급 버전에서는 sudo("exec sudo ... perl -x script")를 통해 Perl을 시작할 수 있습니다.

관련 정보