답변:
이 답변은 Creative Commons Attribution-Share Alike 4.0 라이센스에 따라 사용이 허가 된 Matthew Miller의 Fedora Magazine 원본 기사에서 파생 된 것입니다 .
설명하겠습니다 :
env x='() { :;}; echo OOPS' bash -c :
이렇게하면 취약한 시스템에서“OOPS”가 인쇄되지만 bash가 패치 된 경우 자동으로 종료됩니다.
env x='() { :;}; echo OOPS' bash -c "echo this is a test"
이렇게하면 취약한 시스템에서 "OOPS"가 인쇄되지만 인쇄됩니다. “this is a test” bash가 패치 된 경우에는 됩니다.
그리고 환경 변수와 관련이 있다고 들었을 것입니다. 그러나 왜 환경 변수의 코드가 실행됩니까? 글쎄요,하지만 그럴 필요는 없지만, 자신의 이익을 위해 너무 영리하다고 부르는 기능 때문에 결함이 생길 여지가 있습니다. Bash는 터미널 프롬프트로 볼 수 있지만 스크립팅 언어이며 함수를 정의 할 수 있습니다. 당신은 이렇게 이렇게 :
$ Ubuntu() { echo "Ubuntu is awesome."; }
그리고 새로운 명령이 있습니다. 것을 명심 echo여기에 실제로 아직 실행되지 않고, 새 명령을 실행할 때 발생하는 내용으로 저장되었습니다. 이것은 잠시 후에 중요 할 것입니다!
$ Ubuntu
Ubuntu is awesome.
유능한! 그러나 어떤 이유로 든 하위 프로세스로 새로운 bash 인스턴스를 실행하고 그 아래에서 멋진 새 명령을 실행하려고한다고 가정 해 봅시다. 명령문 bash -c somecommand은 정확히 다음을 수행합니다. 지정된 명령을 새 쉘에서 실행합니다.
$ bash -c Ubuntu
bash: Ubuntu: command not found
아 슬퍼. 자식은 함수 정의를 상속하지 않았습니다. 그러나 셸에서 내 보낸 키-값 쌍의 모음 인 환경이 내재되어 있습니다. (이것은 완전히 '너덜 너덜 한 개념이다; 당신이 이것에 익숙하지 않다면, 지금 나를 믿어 라.) 그리고 bash는 함수를 내보낼 수 있다는 것이 밝혀졌다. 그래서:
$ export -f Ubuntu
$ bash -c Ubuntu
Ubuntu is awesome.
이것이 달성되는 메커니즘이 다소 혼란 스럽다는 것을 제외하고는 모두 훌륭하고 좋은 것입니다 . 기본적으로 환경 변수에서 함수를 수행하기위한 Linux / Unix 매직이 없으므로 내보내기 함수는 실제로 함수 정의를 포함하는 일반 환경 변수를 작성합니다. 그런 다음 두 번째 쉘이 "들어오는"환경을 읽고 함수처럼 보이는 내용을 가진 변수를 만나면이를 평가합니다.
이론적으로 이것은 함수를 정의하는 것이 실제로 실행 되지 않기 때문에 완벽하게 안전 합니다 . 함수 정의의 끝에 도달했을 때 평가가 중단되지 않는 코드에 버그가있었습니다. 그냥 계속 가고있어
로 환경 변수에 저장된 함수가 합법적으로 만들어지면 결코 발생하지 않습니다 export -f. 그러나 왜 합법적입니까? 공격자는 기존 환경 변수를 구성 할 수 있으며, 함수처럼 보이는 경우 새로운 bash 쉘이이를 생각합니다!
첫 번째 예에서
env x='() { :;}; echo OOPS' bash -c "echo this is a test"
env명령은 주어진 변수 세트를 사용해 명령을 실행합니다. 이 경우 x함수처럼 보이는 것으로 설정 합니다. 이 함수는 단지 하나 :입니다. 실제로 아무것도하지 않는 것으로 정의 된 간단한 명령입니다. 그러나 semi-colon함수 정의의 끝을 알리는 뒤에 echo명령이 있습니다. 그것은 거기에 있어야하지 않지만, 우리가 그것을하지 못하게하는 것은 없습니다.
그런 다음,이 새로운 환경에서 실행되도록 지정된 명령은 새로운 bash 쉘이며 다시“ echo this is a test”또는“아무 작업 :”명령을 사용하면 완전히 무해하게 종료됩니다.
그러나-죄송합니다! 새 셸이 시작되고 환경을 읽으면 x변수에 도달 하고 함수처럼 보이므로 평가합니다. 함수 정의는 무해하게로드 된 다음 악의적 인 페이로드도 트리거됩니다. 따라서 취약한 시스템에서 위를 실행하면 “OOPS”다시 인쇄됩니다. 또는 공격자가 인쇄 작업보다 훨씬 더 나쁜 작업을 수행 할 수도 있습니다.
env할 필요가 없습니다. 없이 명령을 사용하면 동일한 결과 (Bash가 업데이트되었는지 여부에 따라 합격 / 불합격)를 얻을 수 있습니다 x='() { :;}; echo OOPS' bash -c "echo this is a test". 변수 할당이있는 명령 앞에는 해당 변수와 해당 값이 명령 ( bash -c "..."이 경우) 환경 으로 전달되기 때문 입니다.
env필요 여부 는 테스트중인 쉘이 아니라 테스트를 실행하는 쉘에 의해 결정됩니다. (이것은 동일 할 수 있습니다. 그럼에도 불구하고 우리는 bash가 자체 환경을 처리하는 방법을 테스트하고 있습니다.) Bourne 스타일 쉘은 NAME=value command구문을 허용 합니다. C 스타일 쉘 (예 : csh, tcsh)은 그렇지 않습니다. 따라서 테스트는 좀 더 이식성이 뛰어납니다 env(때로는 작동 방식에 대한 혼란을 야기하는 비용으로).
에서 의 패치 버전bash 그것을 저장 환경 변수로 함수 정의 수출.
다음 x과 같이 함수 를 저장하십시오 .
$ x() { bar; }
$ export -f x
그리고 그 정의를 확인하십시오.
$ env | grep -A1 x
x=() { bar
}
따라서 자신의 환경 변수를 정의하여이를 악용하고이를 함수 정의로 해석 할 수 있습니다. 예를 들어 env x='() { :;}'로 취급 될 것이다
x() { :;
}
env x='() { :;}; echo vulnerable' bash -c "echo this is a test"
에서 man env,
env -수정 된 환경에서 프로그램을 실행하십시오.
:종료 상태로 종료합니다 0. 참조 더
패치되지 않은 bash의 새 인스턴스가로 시작 bash -c "echo this is a test"되면 만들어진 환경 변수가 함수로 처리되고로드됩니다. 따라서 출력을 얻는다
취약
이것은 시험이다
참고 : bash 시작 중에 함수 정의 외부의 에코가 예기치 않게 실행되었습니다. 함수 정의는 평가 및 악용을 수행하는 단계 일 뿐이며 함수 정의 자체와 사용 된 환경 변수는 임의적입니다. 쉘은 환경 변수를보고 x를보고, 함수 정의가 무엇인지에 대해 알고있는 제약 조건을 충족하는 것처럼 보이고, 의도하지 않게 에코를 실행하여 라인을 평가합니다 (악의적 인 명령이든 상관없이). . 또한 이것을보십시오
env test='() { echo "anything"; }' bash -c "echo otherthing"하면 출력에서 볼 수 있습니다 otherthing. 패치에서 수정되었습니다. 내가 아직 명확하지 않으면 자유롭게 느끼십시오.
unpatched bash정의 된대로 함수를 호출 할 수 있지만 패치 bash에는 정의 자체가 없다는 것입니다.
echo vulnerable) 를 따르는 코드 는 실행되지 않는다는 것입니다. 최신 패치에서 전달 된 함수에는 특정 접두사 ( env 'BASH_FUNC_x()'='() { :;}; echo vulnerable' bash -c "echo this is a test") 가 있어야합니다 . 일부 최신 패치는 %%첫 번째 패치 대신 사용할 수 있습니다 ().