답변:
이 답변은 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"
) 가 있어야합니다 . 일부 최신 패치는 %%
첫 번째 패치 대신 사용할 수 있습니다 ()
.