쉘쇼크


경고. 절대로 따라하지 마세요!

본 문서에는 본인과 타인에게 신체적·물질적인 피해를 입을 위험이 있는 행위에 관한 내용을 포함하고 있습니다. 위 행위를 모방할 시 부상을 당하거나, 물질적으로 피해를 입을 수 있으므로 절대로 따라하지 마시기 바랍니다.


애초에 해킹 분야라서 허가없이 하면 경찰서 간다. 착한 위키러들은 하지말자.

1 개요

Shellshock

2014년 9월 24일에 밝혀진, 유닉스류 운영체제에서 터미널로 사용하는 Bash shell에 존재하는 보안버그.

하트블리드만큼, 아니 그보다 더 심각한 보안버그이다. 하트블리드는 OpenSSL만이 문제였고[1] 그 중에서도 일부 버전(약 2년간 영향을 받음)에만 적용되는데다 이마저도 하트비트 기능을 끄면 안전했다. 하지만 Bash shell은 매우 광범위하게 사용되고 있고[2] 최초로 알려지기 전까지 22년이라는 굉장히 긴 기간 동안 존재해왔기 때문에 하트블리드보다 심각하다고 할 수 있다.

쉘 쇼크에 취약한 버전들은 취약점을 통해 무슨 코드이든 실행 할 수 있게 된다.(보통 root 계정을 탈취한다). 실제로 야후!가 해킹 공격을 당했을 때 사람들이 쉘쇼크를 가장 먼저 생각했을 정도로 발표되자 마자 큰 파장을 불러온 보안버그이다.[3] 이처럼 2014년 10월 말 기에 발견된 이 보안버그는 아직도 현재진행형으로 유닉스 계열의 서버를 사용하는 기업들을 위협하고 있다.

초기 보고 이후로 다양한 쉘 쇼크가 발견되었는데 보통 환경변수를 이용하여 공격한다.

위에 서버가 뚫렸다는 말을 보아 당연한 이야기지만, Shellshock 는 원격(!) 으로도 가능하다! http의 헤더를 변조, 서버에 집적 명령어를 내리는 해킹 방법이 실제로 사용되고 있다.

2 취약점 예제

다음 구문은 CVE-2014-6271[4] 취약점 예제이다.

$ env x='() { :;}; echo vulnerable' bash -c "echo this is a test"

Bash에서 해당 구문을 실행하였을때 다음과 같은 구문이 뜨면 해당 취약점에는 안전한 것이며

this is a test

이렇게 뜬다면 취약한 것이니 빠르게 포맷하도록 하자.[5] 망했어요

vulnerable
this is a test

http 헤더의 User-Agent 부분을 다음과 같이 변조하면 계정 정보를 탈취 가능하다.

User-Agent:() { :; }; echo $(</etc/passwd)

다만 이 경우는 서버가 발신하는 http 헤더에 담겨 있으며, 프록시 툴 없이는 분석이 불가능하다.

Apache서버의 경우 http헤더를 환경변수로 처리하는데 User-Agent가

() {:;}; echo $(</etc/passwd)

로 기록된다. 이 내용을 분석하자면
echo - 뒤에 나오는 내용을 그대로 화면에 출력
$(명령) - 괄호안 명령의 실행 결과를 출력
< - 리디렉션으로 /etc/passwd의 내용을 왼쪽으로 입력. 예제에서는 요청자에게 보낼 http헤더에 입력된다.
/etc/passwd - 리눅스에서 사용자 계정 정보들(사용자이름, 그룹, 홈디렉토리 등등)을 저장하는 파일

이 명령어를 조합하면, "/etc/passwd내용을 http헤더에 출력해서 요청자에게 보낸다" 는 뜻으로 서버측 사용자 계정이 고스란히 노출되는 위험한 상황이다.

다만 일반적인 Apache httpd 서버 운영시에 전부 이 취약점에 노출되는 것이 아니다!! 일반적인 상황에서 Apache 웹 서버가 HTTP 헤더 등을 bash 쉘로 처리할 이유가 전혀 없다. 이는 정확히는 mod_cgi 라는 모듈을 사용하면서, 파일 앞에 #!/bin/bash 를 써주어서 bash 를 사용하겠다고 명시한 cgi 파일들에 한정되는 것이다. 그러니 php 나 기타 일반적인 html 페이지에 아무리 공격을 해봐야 아무 의미 없다. 사실 cgi 는 현재는 잘 사용되지 않는 추세이고, 그나마 있는 것도 Perl 이 대부분이지 쉘로 페이지를 작성하는 경우는 흔하진 않다.

3 예제 설명

본격적으로 설명하기에 앞서 Bash의 환경변수에 대해 간략하게 알아보자.

$ hi="안녕!"
$ echo $hi
안녕!

hi라는 변수를 생성, echo 함수를 통해 출력하는 구문이다. $hi를 입력했을 때 Bash shell은 c의 매크로처럼 "안녕!"이라고 변환해준다.
$ hi="안녕!"
$ export hi
$ printenv | grep hi
hi="안녕!"

이번엔 변수를 선언하고 export를 통해 환경변수에 등록해보자. printenv로 환경변수 목록을 출력해보면 값이 들어가 있는 것을 확인 할 수 있다.

Bash는 위와 같이 변수를 선언해서 환경변수에 넣을 수 있을 뿐만 아니라 함수도 넣을 수 있다.

$ hi() { echo "안녕!"; }
$ hi
안녕!
$ export -f hi
$ printenv | grep hi
hi=() { echo "안녕!"
}

함수를 환경변수에 넣을때는 export에 -f 옵션을 줘서 넣는다. 함수형 환경변수가 저장되는 방식을 유심히 살펴보자

자 이제 본격적으로 CVE-2014-6271 취약점에 대해 알아보자. 해당 취약점은 함수가 아닌 일반 환경 변수가 () { <함수 body> }; <공격하려는 코드> 이런 모양일 경우 child로 생성된 Bash shell에서 함수로 인식되는 버그이다.

$ export hi='() { echo "안녕!"; }; echo "꺼져";' #함수가 아닌 일반 환경변수 hi를 넣는다

$ bash #새 Bash를 생성
"꺼져" #공격하려는 코드가 인식되어 실행된다.

마지막으로 위의 예제를 살펴보자

$ env x='() { :[6];}; echo vulnerable' bash -c "echo this is a test"

env라는 명령어는 '해당 환경변수를 가지고 명령을 실행해라'는 뜻이다. 즉, x='() { :;}; echo vulnerable' 환경변수를 가지고 bash -c "echo this is a test" 라는 구문을 실행하게 되는 것.
만약 취약점에 노출되었다면 뒤에 있는 echo vulnerable이라는 구문이 실행 될 것이다.

  1. 다른 TLS 프로그램들은 문제가 없다
  2. OS X안드로이드도 잠재적으로 이 버그에 취약할 수 있다.
  3. 확인 결과 쉘쇼크가 아닌 익스플로잇을 조작해서 우회 공격이었다. 다행히도 야후!는 개인정보가 해킹당하지 않았다고 한다.
  4. 최초로 보고된 쉘 쇼크이다
  5. 취약점 패치만 가지고는 안된다. 이미 악의적인 코드가 실행되어 계정이 탈취된 경우 백도어나 루트킷이 깔려 있을 수 있고(공격에 성공하면 보통 이런 것들을 깐다고 보면 된다.), 이런 경우 악의적인 유저는 정상적인 접근을 통해 시스템을 제어할 수 있기 때문에 해당 취약점을 막아도 소용이 없고, 발견하기도 힘들다.
  6. : 라는 기호는 Bash shell에서는 true와 동치이다.