Linux는 해석 된 모든 실행 파일 (즉, #!
줄로 시작하는 실행 파일)에서 setuid¹ 비트를 무시합니다 . comp.unix.questions 자주 묻는 질문은 이 setuid 쉘 스크립트와 보안 문제를 설명합니다. 이러한 문제는 두 가지 종류가 있습니다 : shebang 관련 및 shell 관련; 자세한 내용은 아래를 참조하십시오.
보안에 신경 쓰지 않고 setuid 스크립트를 허용하려면 Linux에서 커널을 패치해야합니다. 3.x를 커널로, 나는 당신이 전화를 추가 할 필요가 있다고 생각 install_exec_creds
에 load_script
호출하기 전에, 기능 open_exec
,하지만 테스트하지 않았습니다.
세이트 세방
shebang ( #!
)이 일반적으로 구현 되는 방식에 고유 한 경쟁 조건이 있습니다 .
- 커널은 실행 파일을 열고로 시작하는 것을 찾습니다
#!
.
- 커널은 실행 파일을 닫고 인터프리터를 대신 엽니 다.
- 커널은 스크립트의 경로를 인수 목록 (
argv[1]
)에 삽입하고 인터프리터를 실행합니다.
이 구현에서 setuid 스크립트가 허용되는 경우 공격자는 기존 setuid 스크립트에 대한 심볼릭 링크를 생성하고 실행하여 커널이 1 단계를 수행 한 후 및 인터프리터가 도착하기 전에 링크를 변경하여 임의의 스크립트를 호출 할 수 있습니다. 첫 번째 논쟁을여십시오. 이러한 이유로, 대부분의 유니스 는 셰방을 감지 할 때 setuid 비트를 무시합니다 .
이 구현을 보호하는 한 가지 방법은 커널이 인터프리터가 파일을 열 때까지 스크립트 파일을 잠그는 것입니다 (이것은 파일을 링크 해제하거나 덮어 쓰는 것뿐만 아니라 경로의 디렉토리 이름을 바꾸는 것을 방지해야 함). 그러나 유닉스 시스템은 필수 잠금에서 벗어나는 경향이 있으며 기호 링크는 올바른 잠금 기능을 특히 어렵고 침습적으로 만듭니다. 아무도 그렇게하지 않는다고 생각합니다.
몇 유닉스 시스템 (설정 커널을 필요로 모두 주로 오픈 BSD, NetBSD의 및 Mac OS X가 활성화 될)를 구현 보안이 setuid 오두막을 추가 기능을 사용 : 경로가 이미 파일 기술자에 열린 파일을 참조 N (그래서 개방 입니다 대략)와 같습니다 . Linux를 포함한 많은 유닉스 시스템 에는 setuid 스크립트 가 있지만 설정되어 있지 않습니다./dev/fd/N
/dev/fd/N
dup(N)
/dev/fd
- 커널은 실행 파일을 열고로 시작하는 것을 찾습니다
#!
. 실행 파일의 파일 디스크립터가 3이라고 가정하십시오.
- 커널이 인터프리터를 엽니 다.
- 커널
/dev/fd/3
은 인수 목록 ( argv[1]
)을 삽입 하고 인터프리터를 실행합니다.
Sven Mascheck의 shebang 페이지 에는 setuid 지원을 포함하여 unices에 대한 shebang 에 대한 많은 정보가있습니다.
Setuid 통역사
OS가 setuid shebang을 지원하거나 기본 바이너리 래퍼 (예 :)를 사용했기 때문에 프로그램을 루트로 실행했다고 가정 해 봅시다 sudo
. 보안 구멍을 열었습니까? 아마 . 여기서 문제는 해석 된 프로그램과 컴파일 된 프로그램에 관한 것이 아닙니다 . 문제는 권한으로 실행되는 경우 런타임 시스템 이 안전하게 동작 하는지 여부 입니다.
동적으로 연결된 네이티브 바이너리 실행 파일은 프로그램에 필요한 동적 라이브러리를로드하는 동적 로더 (예 :)에 의해 해석되는 방식 /lib/ld.so
입니다. 많은 유니스에서 환경을 통해 동적 라이브러리의 검색 경로를 구성하고 ( LD_LIBRARY_PATH
환경 변수의 일반적인 이름 임) 실행 된 모든 바이너리 ( LD_PRELOAD
)에 추가 라이브러리를로드 할 수도 있습니다. 프로그램의 호출자는 특수하게 조작 libc.so
된 $LD_LIBRARY_PATH
(다른 전술 중에서) 배치함으로써 해당 프로그램의 컨텍스트에서 임의의 코드를 실행할 수 있습니다 . 모든 제정신 시스템 LD_*
은 setuid 실행 파일 의 변수를 무시합니다 .
에서 껍질 같은 SH, CSH 및 유도체, 환경 변수 자동 쉘 매개된다. PATH
, 등의 매개 변수를 통해 IFS
스크립트 호출자는 쉘 스크립트 컨텍스트에서 임의의 코드를 실행할 수있는 많은 기회가 있습니다. 일부 셸은 스크립트가 권한으로 호출 된 것을 감지하면 이러한 변수를 적절한 기본값으로 설정하지만, 신뢰할만한 특정 구현이 있는지는 알 수 없습니다.
대부분의 런타임 환경 (기본, 바이트 코드 또는 해석)은 비슷한 기능을 가지고 있습니다. setuid 실행 파일에서 특별한 예방 조치를 취하는 사람은 거의 없지만 기본 코드를 실행하는 작업은 동적 연결 (예방 조치가 필요함)보다 더 멋진 일을하지 않는 경우가 많습니다.
Perl 은 주목할만한 예외입니다. 그것은 명시 적으로이 setuid 스크립트를 지원하는 안전한 방법입니다. 실제로, OS에서 스크립트의 setuid 비트를 무시하더라도 스크립트는 setuid를 실행할 수 있습니다. 이는 perl에 필요한 검사를 수행하고 원하는 권한으로 원하는 스크립트에서 인터프리터를 다시 호출하는 setuid 루트 도우미와 함께 제공되기 때문입니다. 이것은 perlsec 매뉴얼에 설명되어 있습니다. 그것은이 setuid 펄 스크립트가 필요하다는로 사용 #!/usr/bin/suidperl -wT
대신 #!/usr/bin/perl -wT
하지만, 대부분의 현대 시스템에 #!/usr/bin/perl -wT
충분하다.
네이티브 이진 래퍼 를 사용하면 이러한 문제를 방지하기 위해 자체적으로 아무 것도 수행하지 않습니다 . 실제로 런타임 환경이 특권으로 호출되고 런타임 구성 가능성을 무시하고 있음을 감지하지 못할 수 있으므로 상황을 악화시킬 수 있습니다.
랩퍼 가 환경을 삭제하면 원시 바이너리 랩퍼가 쉘 스크립트를 안전하게 만들 수 있습니다 . 스크립트는 너무 많은 가정을하지 않도록주의해야합니다 (예 : 현재 디렉토리). 환경을 위생 처리하도록 설정된 경우 sudo를 사용할 수 있습니다. 블랙리스트 변수는 오류가 발생하기 쉬우므로 항상 화이트리스트에 올리십시오. sudo를 함께, 있는지 확인 env_reset
옵션 즉, 온 setenv
오프, 그리고 그 env_file
와 env_keep
단지 무해한 변수가 포함되어 있습니다.
TL, DR :
- Setuid shebang은 안전하지 않지만 일반적으로 무시됩니다.
- 특권 (sudo 또는 setuid를 통해)으로 프로그램을 실행하는 경우 원시 코드 또는 perl을 작성하거나 환경을 삭제하는 랩퍼 (예 :
env_reset
옵션을 사용하여 sudo)로 프로그램을 시작하십시오 .
¹ 이 설명은 "setgid"를 "setuid"로 대체하는 경우에도 동일하게 적용됩니다. 스크립트에서 Linux 커널에 의해 무시됩니다.