실행만 되는 파일에 대해서는 누가 인터프리터를 실행합니까?

실행만 되는 파일에 대해서는 누가 인터프리터를 실행합니까?

#!/path/to/interpreter현재 사용자에게 파일에 대한 실행(--x) 권한만 있는 경우 어떤 사용자 아래에서 인터프리터(파일 시작 부분에 지정됨 )가 실행됩니까?

현재 사용자는 파일을 읽을 수 있는 권한이 없기 때문에 해당 사용자가 될 수 없습니다. 인터프리터에 포함된 모든 코드는 루트 액세스 권한을 가지므로 루트일 수 없습니다.

그렇다면 인터프리터 프로세스는 어떤 사용자로 실행됩니까?

편집: 내 질문은 파일이 지정하는 통역사를 알 수 있을 만큼 충분히 읽었다고 가정하지만 실제로는 그렇게까지 도달하지 못한다고 생각합니다. 현재 쉘(보통 b/a/sh)이 대상 파일을 실행하기 위해 해석하는 명령은 해당 파일을 읽으려고 시도하지만 실패합니다.

답변1

사용자에게 실행 가능한 스크립트에 대한 읽기 권한이 없으면 실행해 보십시오.실패하다CAP_DAC_OVERRIDE, 그녀에게 능력이 없는 경우 (예: 루트인 경우):

$ cat > yup; chmod 100 yup
#! /bin/sh
echo yup
^D
$ ./yup
/bin/sh: 0: Can't open ./yup

인터프리터는 (실패 또는 성공에 관계없이) 스크립트의 setuid 비트 또는 setcap 확장 속성을 무시하고 항상 현재 사용자로 실행됩니다.

실행 가능한 스크립트는 실행하기 위해 인터프리터가 열고 읽을 수 있어야 한다는 점에서 바이너리와 다릅니다. 그러나 이는 단순히 인터프리터에 인수로 전달되며, 인터프리터는 이를 전혀 읽으려고 시도하지 않고 대신 완전히 다른 작업을 수행할 수 있습니다.

$ cat > interp; chmod 755 interp
#! /bin/sh
printf 'you said %s\n' "$1"
^D
$ cat > script; chmod 100 script
#! ./interp
nothing to see here
^D
$ ./script
you said ./script

물론 번역가는그 자체setuid 또는 cap_dac_override=ep-setcap 바이너리일 수 있습니다(또는 해당 바이너리에 대한 인수로 스크립트 경로를 전달). 이 경우 높은 권한으로 실행되며 모든 파일 권한은 무시될 수 있습니다.

Linux에서 binfmt_misc를 통해 읽을 수 없는 Setuid 스크립트

Linux에서는 다음 모듈을 사용하여 실행 가능한 스크립트의 모든 제한을 우회할 수 있습니다(그리고 시스템을 손상시킬 수 있습니다 ;-)) binfmt_misc.

루트로서:

# echo ':interp-test:M::#! ./interp::./interp:C' \
    > /proc/sys/fs/binfmt_misc/register

# cat > /tmp/script <<'EOT'; chmod 4001 /tmp/script # just exec + setuid
#! ./interp
id -u
EOT

일반 사용자로서:

$ echo 'int main(void){ dup2(getauxval(AT_EXECFD), 0); execl("/bin/sh", "sh", "-p", (void*)0); }' |
    cc -include sys/auxv.h -include unistd.h -x c - -o ./interp
$ /tmp/script
0

여피족 에 태어난 젊은 엘리트 층!

자세한 내용은 다음을 참조하세요.Documentation/admin-guide/binfmt-misc.rst커널 소스 코드에서.

-p옵션은 일부 셸에서 오류를 일으킬 수 있지만(옵션은 간단히 제거할 수 있음) 최신 버전에서는 오류를 방지하려면 dash이 옵션이 필요합니다.bash특권을 포기하다요청 없이도.

답변2

스크립트 실행에는 두 단계가 있습니다. 먼저 커널은 파일의 시작 부분을 읽고 로 시작하는 것을 찾아서 #!다음과 같이 읽습니다.셰르본어떤 통역사에게 전화할지 결정하세요. 그런 다음 커널은 원시 명령줄을 인터프리터 경로, shebang 줄의 옵션(있는 경우), 파일 경로 및 원시 옵션으로 변환합니다. 그런 다음 이 명령줄을 항상 명령줄이었던 것처럼 실행하지만 추가 Shebang 처리는 수행하지 않습니다.

지금까지 커널은 호출자가 스크립트 파일에 대한 실행 권한을 가지고 있는지 확인했습니다. 읽기 권한이 아직 적용되지 않았습니다. 커널은 파일이 실행되는 동안 파일의 시작 부분을 읽으므로 이는 읽기 권한이 아닌 실행 권한에 의해 제어됩니다.

두 번째 단계에서는 인터프리터가 실행됩니다. 명령줄에서 스크립트 파일 이름을 확인하므로 해당 파일을 열려고 시도할 수 있습니다. 이때 읽기 권한이 필요합니다. 인터프리터가 파일을 읽을 수 있는 권한이 없으면 호출이 open실패하고 인터프리터는 오류 메시지를 인쇄하고 포기할 수 있습니다. 내가 "아마도"라고 말한 이유는 그것이 모든 합리적인 통역사가 하는 일이기 때문입니다. 그러나 그런 식으로 일이 발생해야 하는 기술적인 의무는 없습니다. Shebang 라인에서 사용하는 프로그램이 통역사가 아닌 경우 첫 번째 단계에서는 아무런 차이가 없지만 프로그램은 두 번째 단계에서 해당 작업을 수행합니다. 예를 들어, "script"로 시작하면 #!/bin/echo스크립트 파일 이름과 기타 명령줄 인수가 인쇄된 다음 종료되며 스크립트는 이에 대해서만 실행 가능해야 합니다.

1Linux를 포함한 많은 커널은 하나만 선택할 수 있습니다.

답변3

일반적으로 파일을 소유하고 있더라도 "r" 권한이 없으면 스크립트를 실행할 수 없습니다.

$ ls -l tst
---x--x--x 1 sweh sweh 24 May  4 21:22 tst*

$ ./tst
/bin/bash: ./tst: Permission denied

$ sudo cat tst
#!/bin/bash

echo hello

수정된 질문을 기반으로 합니다.

프로그램의 이 부분은 #!커널에 의해 exec()시스템 호출의 일부로 해석됩니다. 따라서 이를 달성하기 위해 스크립트를 읽을 수 있을 필요는 없습니다.

내 예에서 실제로 일어나는 일은 커널이 my를 호출 ./tst로 변환하는 것입니다./bin/bash ./tst

이 변환은 스크립트를 r처리하기 위해 액세스가 필요한 이유를 설명하지만 커널은 x사용할 인터프리터만 결정하면 됩니다.

관련 정보