bash에서 내장 명령을 명시적이고 안전하게 사용하는 방법


19

있습니다 비슷한 질문은 당신이 예를 들어 대체 할 '포장'시나리오와 거래 cd내장을 호출하는 명령 cd.

그러나 shellshock et al과 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가 내장 명령을 안전하게 사용하도록하거나 강제로 전체 환경을 지우지 않고 명령이 내장되지 않은 것을 감지하는 방법이 있습니까?

누군가가 환경을 제어하는 ​​경우 어쨌든 망친 것일 수도 있지만 적어도 별칭의 경우 \앞에 를 삽입하여 별칭을 호출하지 않는 옵션이 있습니다.


다음 env과 같이 명령을 사용하여 스크립트를 실행할 수 있습니다 .env -i <SCRIPT.sh>
Arkadiusz Drabczyk

env함수로 다시 정의되지 않은 경우에만 . 이것은 끔찍하다. 처음에는 특수 문자가 도움이 될 것이라고 생각했습니다 . 소스를 /사용 .하는 등의 전체 경로로 호출 하는 등. 그러나 이것들은 함수 이름에도 사용될 수 있습니다! 당신은 할 수 있습니다 당신이 원하는 모든 기능을 재정의하지만, 원래의 명령을 호출로 돌아 가야 어렵다.
오리온

1
사실, 손상된 시스템에서 스크립트를 실행하려는 경우 어쨌든 문제가 발생합니다. 또는 #/bin/sh기본 대화식 쉘이 아닌 경우 스크립트를 작성하십시오 .
Arkadiusz Drabczyk

답변:


16

Olivier D는 거의 정확하지만 POSIXLY_CORRECT=1실행하기 전에 설정 해야합니다 unset. POSIX에는 Special Built-ins 개념이 있으며 bash는이를 지원합니다 . unset그런 내장 중 하나입니다. 검색 SPECIAL_BUILTIN에서 builtins/*.c목록 bash는 소스, 그것은 포함 set, unset, export, evalsource.

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

도적은 unset이제 설정을 해제하면 환경에서 제거 된 command, type, builtin다음 진행할 수 있어야하지만 unset POSIXLY_CORRECT이 아닌 POSIX의 행동이나 고급 Bash의 기능에 의존하는 경우.

이것은 별명을 다루지 않으므로\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[[예약어 및 예방 조치가 필요하지 않습니다.) 우리가 사용하는 참고 unset -f해제 기능을 확인하기 위해, 변수와 함수가 같은 공간을 공유하지만이 동시에 (ETAN Reisner 덕분에) 경우에 존재하는 것이 가능 두 번 설정 해제하면 트릭이 수행됩니다. 당신은 할 수 있습니다 , 배쉬는 당신이 읽기 전용 기능을 설정 해제 및 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

(그리고 오류를 무시하십시오) 또는 다른 scriptobatics에 관여 하십시오 .


기타 참고 사항 :

  • function예약어이므로 별칭을 지정할 수 있지만 함수로 재정의 할 수는 없습니다. (앨리어싱 function은 우회하는 방법으로 허용 \function 되지 않기 때문에 약간 번거 롭습니다)
  • [[, ]]예약어이며 별칭을 지정할 수 있지만 (무시 됨) 함수로 재정의되지 않습니다 (함수의 이름을 지정할 수 있음)
  • (( 함수의 별칭이나 별칭이 아닙니다.

흥미 롭습니다, 고마워요! 그 떠들썩한 파티가 기본 것이 나에게 이상한 것 같습니다 하지 보호 unset덮어되는 것을 등.
falstro

그렇지 않은 -f논쟁 이 필요 unset합니까? 그렇지 않으면 내장 함수와 같은 이름의 변수와 함수가 모두 정의 된 unset경우 변수를 먼저 선택하여 설정을 해제합니다. 모호한 기능 중 하나라도 설정되어 readonly있지 않으면 실패 합니다. (이것은 감지 가능하고 치명적인 오류가 발생할 수 있습니다.) 또한 이것은 [내장 된 것처럼 보입니다.
Etan Reisner

1
\unset -f unset읽기 루프에서 수행되므로 의미가 있다고 생각하지 않습니다 . unset함수 인 경우 \unset일반적으로 내장 된 대신 함수로 해결하지만 \unsetPOSIX 모드가 적용되는 한 안전하게 사용할 수 있습니다 . 명시 적 \unset -f으로 [,을 (를 .) 호출 하면 :정규식에서 제외하므로 좋은 아이디어 일 수 있습니다. 또한 루프에 in을 추가 -f하고 이전 대신 루프 이후 \unset에 추가 합니다 \unset POSIXLY_CORRECT. \unalias -a(이후 \unset -f unalias)는 후속 명령에서 탈출을 안전하게 포기할 수 있습니다.
Adrian Günter

1
@ AdrianGünter Try : [[ ${POSIXLY_CORRECT?non-POSIX mode shell is untrusted}x ]], 이렇게하면 변수가 설정되지 않은 경우 표시되는 오류와 함께 비 대화식 스크립트가 종료되거나 설정되어있는 경우 (빈 또는 값) 계속됩니다.
mr.spuratic

1
"사용해야합니다 \unset"... 문자를 인용하면 첫 번째 문자뿐만 아니라 별칭 확장도 피할 수 있습니다. un"se"t읽기 쉽지는 않지만 잘 작동합니다. "인용되지 않은 경우 각 간단한 명령의 첫 단어는 별명이 있는지 확인합니다." – Bash Ref
Robin A. Meade

6

누군가가 당신의 환경을 통제한다면 당신은 어쨌든 망 쳤을 것입니다.

응 그거. 알 수없는 환경에서 스크립트를 실행 LD_PRELOAD하면 셸 프로세스가 스크립트를 읽기 전에 임의의 코드를 실행하는 것으로 시작하여 모든 방식이 잘못 될 수 있습니다 . 스크립트 내부에서 적대적인 환경으로부터 보호하려고 시도하는 것은 쓸데없는 일입니다.

Sudo는 10 년 이상 bash 함수 정의처럼 보이는 것을 제거하여 환경을 위생적으로 관리해 왔습니다. Shellshock 이후 완전히 신뢰할 수없는 환경에서 쉘 스크립트를 실행하는 다른 환경이 적합했습니다.

신뢰할 수없는 엔터티가 설정 한 환경에서는 스크립트를 안전하게 실행할 수 없습니다. 따라서 함수 정의에 대한 걱정은 생산적이지 않습니다. 환경을 위생 처리하고 bash에서 함수 정의로 해석하는 변수를 삭제하십시오.


1
나는 이것에 전적으로 동의하지 않습니다. 보안은 "위생 화"또는 "위생 화되지 않은"중심의 이진 제안이 아닙니다. 악용 기회를 제거하는 것입니다. 불행히도 현대 시스템의 복잡성으로 인해 제대로 잠겨 야하는 많은 개발 기회가 있습니다. 많은 착취 기회는 PATH 변수 변경, 내장 함수 재정의 등 무해한 업스트림 공격을 중심으로합니다. 한 사람이나 프로그램에게 기회를 제공하면 전체 시스템이 취약합니다.
Dejay Clayton 2016

@ DejayClayton 나는 첫 번째 문장을 제외하고는 귀하의 의견에 전적으로 동의합니다. 공격 기회를 제거하면 도움이되지만 공격의 사소한 조정만으로도 계속 작동 할 수있는 절반은 제거 할 수 없습니다.
Gilles 'SO- 악마 그만해'

요점은 "환경을 위생 처리"할 수없고 다양한 공격 경로에 대해 걱정할 필요가 없다는 것입니다. 때로는 "스크립트 내부에서 적대적인 환경으로부터 보호"하기 위해 비용을 지불합니다. "함수 정의"문제를 해결하더라도 "cat"또는 "ls"라는 사용자 정의 스크립트를 디렉토리에 넣을 수있는 PATH와 "cat"을 호출하는 모든 스크립트에 대해 걱정해야합니다 "/ bin / cat"및 "/ bin / ls"대신 "또는"ls "가 효과적으로 악용을 실행하고 있습니다.
Dejay Clayton

@DejayClayton 분명히 환경을 위생 처리하는 것은 환경과 관련이없는 공격 경로에 도움이되지 않습니다. (예를 들어 /bin/catchroot에서 호출하는 스크립트는 무엇이든 호출 할 수 있습니다.) 환경을 위생 처리하면 제정신이됩니다 PATH(물론 제대로 수행한다고 가정). 나는 아직도 당신의 요점을 보지 못하고 있습니다.
Gilles 'SO- 악마 그만해'

PATH는 익스플로잇의 가장 큰 기회 중 하나이며 많은 의심스러운 PATH 사례는 보안 블로그에서도 권장 조언으로 문서화되어 있으며 때로는 설치된 응용 프로그램이 PATH를 재정렬하여 이러한 앱이 작동하도록하는 방법을 고려할 때 스크립트 내에서 방어 코딩은 나쁜 생각입니다. 제정신 PATH라고 생각하는 것은 실제로는 경험하지 못한 악용에 취약 할 수 있습니다.
Dejay Clayton

1

unset -f내장 기능, 명령 및 유형을 제거하는 데 사용할 수 있습니다 .


2
미안 unset() { true; }합니다.
falstro

1
제길! 정의 된 함수를 나열하는 것도 내장 기능에 의존합니다. 나는 포기한다!
odc
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.