Bash에서 내장 명령을 명시적이고 안전하게 강제하는 방법

Bash에서 내장 명령을 명시적이고 안전하게 강제하는 방법

하나 있다유제cd내장 호출을 대체하려는 경우와 같은 "래퍼" 시나리오를 처리합니다 cd.

그러나 shellshock 등을 고려하고 bash가 환경에서 함수를 가져오는 것을 알고 몇 가지 테스트를 수행했지만 cd스크립트 내에서 내장 함수를 안전하게 호출하는 방법을 찾을 수 없었습니다.

이것에 대해 생각하다

cd() { echo "muahaha"; }
export -f cd

이 환경에서 사용법 호출을 사용하는 모든 스크립트 cd는 중단됩니다(유사한 효과 고려 cd dir && rm -rf .).

명령어의 종류를 확인하는 명령어(편의상 이라고 함 )와 함수( 및 ) type대신 내장된 버전을 실행하는 명령어가 있습니다. 그러나 보라, 이것들은 함수를 사용하여 재정의될 수도 있다.builtincommand

builtin() { "$@"; }
command() { "$@"; }
type() { echo "$1 is a shell builtin"; }

다음과 같은 결과가 생성됩니다.

$ type cd
cd is a shell builtin
$ cd x
muahaha
$ builtin cd x
muahaha
$ command cd x
muahaha

bash가 내장 명령을 사용하도록 안전하게 강제하거나 적어도 전체 환경을 지우지 않고 명령이 내장 명령이 아니라는 것을 감지할 수 있는 방법이 있습니까?

누군가가 귀하의 환경을 제어하면 문제가 발생할 수 있지만 최소한 별칭을 사용하면 \별칭 앞에 를 삽입하여 별칭을 호출하지 않도록 선택할 수 있습니다.

답변1

올리비에 D.거의정확합니다. 하지만 POSIXLY_CORRECT실행하기 전에 설정 해야 합니다 unset. POSIX에는 개념이 있습니다특수 내장, 그리고배쉬는 이것을 지원합니다. unset그것은 단지 내장되어 있습니다. , 및 가 포함 된 찾기 목록 SPECIAL_BUILTIN에서 bash 소스를 검색합니다 .builtins/*.csetunsetexportevalsource

$ unset() { echo muahaha-unset; }
$ unset unset
muahaha-unset
$ POSIXLY_CORRECT=1
$ unset unset

이제 불량은 환경에서 제거 되며 , unset설정을 해제하면 계속할 수 있지만 나중에 POSIX가 아닌 동작이나 고급 bash 기능에 의존하는 경우에는 계속할 수 없습니다.commandtypebuiltinunset POSIXLY_CORRECT

이것확실히하지만 주소는 별칭이므로 다음을 사용해야 합니다 \unset(또는어떤 형태의 인용/이스케이프대화형 셸에서 작동하는지 확인하기 위해(또는 expand_aliases작동하는 경우를 대비해 항상)

편집증 환자에게 이것은~해야 한다모든 문제를 해결하려면 다음과 같이 생각합니다.

POSIXLY_CORRECT=1
\unset -f help read unset
\unset POSIXLY_CORRECT
re='^([a-z:.\[]+):' # =~ is troublesome to escape
while \read cmd; do 
    [[ "$cmd" =~ $re ]] && \unset -f ${BASH_REMATCH[1]}; 
done < <( \help -s "*" )

( while, do, done[[는 예약어이므로 주의가 필요하지 않습니다. =별칭이나 함수 이름에는 사용할 수 없으므로 설정 시 주의가 필요하지 않습니다 .) 변수와 함수가 공유하더라도 함수가 설정 해제되었는지 확인하기 위해 POSIXLY_CORRECT사용한다는 점에 유의하세요. unset -f동일한 명명 공간이 있으면 둘 다 동시에 존재할 수 있습니다(Etan Reisner 덕분에). 이 경우 설정을 두 번 해제하면 문제가 해결됩니다. 너할 수 있는기능을 읽기 전용으로 표시하세요. bash는 bash-4.2 및 이전 버전에서 읽기 전용 기능을 설정 해제하는 것을 막지 않습니다. bash-4.3은 여러분을 막지만, POSIXLY_CORRECT설정할 때 특수 내장 기능을 여전히 존중합니다.

읽기 전용은 POSIXLY_CORRECT실제 문제가 아니며 부울이나 플래그도 아닙니다.현재의POSIX 모드를 활성화하므로 읽기 전용으로 존재하는 경우 값이 비어 있거나 0이더라도 POSIX 기능을 사용할 수 있습니다. 위와는 다르게 문제가 되는 기능을 설정 해제하면 됩니다. 아마도 잘라내기와 붙여넣기를 사용하면 됩니다.

\help -s "*" | while IFS=": " read cmd junk; do echo \\unset -f $cmd; done

(그리고 오류를 무시하거나) 다른 일에 참여하십시오.문자론.


기타 참고사항:

  • function예약어이며 별칭으로 사용할 수 있지만 함수로 재정의할 수는 없습니다. (앨리어싱은 function조금 귀찮습니다.\function 아니요이 문제를 해결하는 방법으로 허용됩니다)
  • [[, ]]예약어이며 별칭을 지정할 수 있지만(무시됨) 함수에 의해 재정의될 수 없습니다(함수 이름은 그렇게 지정될 수 있음)
  • ((함수 또는 별칭의 유효한 이름이 아닙니다.

추가 제안을 해주신 아래 댓글 작성자에게 감사드립니다.

답변2

나는 누군가가 당신의 환경을 통제한다면 당신은 망할 수도 있다는 것을 깨달았습니다.

그래 그거야. 알 수 없는 환경에서 스크립트를 실행하면 LD_PRELOAD스크립트를 읽기 전에 쉘 프로세스가 임의의 코드를 실행하는 것부터 시작하여 다양한 문제가 발생할 수 있습니다 . 스크립트 내에서 적대적인 환경으로부터 보호하려는 시도는 소용이 없습니다.

10년 넘게 Sudo는 bash 함수 정의처럼 보이는 모든 것을 제거하여 환경을 위생적으로 유지해 왔습니다. ~부터쉘 쇼크, 완전히 신뢰할 수 없는 환경에서 쉘 스크립트를 실행하는 다른 환경도 이에 따랐습니다.

신뢰할 수 없는 엔터티가 설정한 환경에서는 스크립트를 안전하게 실행할 수 없습니다. 따라서 함수 정의에 대해 걱정하는 것은 비생산적입니다. 환경을 정리하면 bash는 변수를 함수 정의로 해석합니다.

답변3

이 명령을 사용하여 함수 및 을 unset -f 삭제할 수 있습니다 .builtincommandtype

관련 정보