▷ 작성자 : 붉은반점(r3dp0int@a3sc.co.kr)
▷ 편집자 : 니키 (
ngnicky@a3sc.co.kr)



FreeBSD 7.0-RELEASE Telnet Daemon
Local Privilege Escalation Exploit



취약점

FreeBSD Telnetd Remote Code Execution 취약점

A3SC Advisory ID

 

위험등급

최초 발표일

2009 2

문서 작성일

2009 2 25

벤더

FreeBSD

현재상태(패치여부)

홈페이지 패치 가능


1. 요약
FreeBSD 텔넷 데몬(telnet(8))은 Telnet 가상 터미널 프로토콜의 서버를 구축하는데 사용하는 데몬입니다. 하지만, 보안의 이유로 2001년 8월부터 FreeBSD에서는 텔넷 대신 SSH프로토콜을 사용할 것을 권고해왔습니다. 텔넷 프로토콜은 접속한 클라이언트가 새롭게 생성된 로그인 세션에 대해 설정될 수 있는 환경변수를 직접 지정할 수 있도록 허가합니다. 이걸 사용하여 터미널 설정 등을 정할 수가 있게 됩니다.

이 점을 이용한 환경변수 기반의 공격을 막기 위해서는 텔넷 데몬이 해가 되는 환경변수 부분을 제거해주어야 합니다. 하지만, 환경변수 부분을 제대로 체크하지 못하는 점을 이용하여 텔넷 접속 시 root 권한으로 접속하여 코드 실행이 가능한 취약점입니다.


2. 취약점 대상
 FreeBSD (7.0 – Release) 버전
 FreeBSD (7.1 – Release) 버전


3. 취약점 영향

본 취약점은 아래와 같은 영향을 줄 수 있습니다.

취약점 영향

위험도

시스템 중요파일 변경 가능

시스템 코드 실행 가능




II. 취약점 상세분석

1. 취약점 개요
본 취약점은 /bin/login을 실행시키기 이전 단계에서 환경변수 LD_PRELOAD같이 LD_*를 체크하지 않아서 생기는 취약점입니다. 이는 원격에서 root권한으로 코드를 실행할 수 있습니다.

[program.c 원본 : http://www.milw0rm.com/exploit/8055] 일부 수정하였음.

이를 아래의 명령어를 이용하여 컴파일 할 것입니다.

#gcc –o program.o –c program.c –fPIC
#gcc –shared –Wl, -soname, libno_ex.so.1 –o libno_ex.so.1.0 program.o –nostartfiles

정상적으로 실행하였다면 아래 그림과 같이 파일이 존재하는 것을 확인할 수 있습니다.


[그림 1] 디렉토리 내 생성된 파일 확인

이중 라이브러리 함수를 쉽게 알 수 있는 임의의 위치에 복사를 해 놓습니다.
#cp libno_ex.so.1.0 /tmp/libno_ex.so.1.0

이 취약점을 실제 공격에 이용하기 위해서는 위와 같이 다른 공격을 이용하여 알려진 위치에 LD_PRELOAD 환경변수를 설정해놓은 다음 telnet을 이용하여 원격 혹은 로컬로 Root 권한을 얻어 낼 수 있게 됩니다.

이제는 위와 같은 과정을 거쳐 목표 서버에 환경설정을 완료했다는 가정하에 Telnet을 이용하여 Root 권한을 얻도록 하겠습니다.

telnet 을 열어 SRA(Secure RPC Authentication)을 끄고, 환경설정을 위해 심어놓은 라이브러리를 불러들여 권한상승을 실행할 수 있도록 합니다.

몇 줄 되지 않지만, 실행하면 아래의 그림과 같이 Root 만의 기호 #을 볼 수 있게 됩니다. 권한 비교 및 확인을 위해 id 명령어를 이용하였습니다.


[그림 2] Telnet 접속 시 환경설정을 이용하여 권한 상승에 성공한 화면
위와 같이 Telnet 을 이용해 권한 상승에 성공하였음을 확인하였습니다.


2. 소스코드 패치 분석
= 패치 시 삭제될 부분
= 패치 시 추가될 부분

  char **cpp, **cpp2;
  const char **p;
-
-  for (cpp2 = cpp = environ; *cpp; cpp++) {

+ char ** new_environ;
+ size_t count;
+
+ /* Allocate space for scrubbed environment. */
+ for (count = 1, cpp = environ; *cpp; count++, cpp++)
+  continue;
+ if ((new_environ = malloc(count * sizeof(char *))) == NULL) {
+  environ = NULL;
+  return;
+ }
+
+  for (cpp2 = new_environ, cpp = environ; *cpp; cpp++) {
   int reject_it = 0;
 
   for(p = rej; *p; p++)
@@ -1286,10 +1296,15 @@
   for(p = acc; *p; p++)
    if(strncmp(*cpp, *p, strlen(*p)) == 0)
     break;
-  if(*p != NULL)
-    *cpp2++ = *cpp;

+  if(*p != NULL) {
+   if ((*cpp2++ = strdup(*cpp)) == NULL) {
+    environ = new_environ;
+    return;
+   }
+  }
   }
  *cpp2 = NULL;
+ environ = new_environ;
 }


주요 패치 내용 )
새로운 포인트 변수 new_environ을 할당하고, 만약 환경변수 environ에 환경변수가 등록되어 있으면 이 값을 지워버리고 new_environ에 입력하여 environ 값으로 바꿔줍니다.



III. 결론

1. 대응 방안

근본적인 문제해결은 있을 수 없습니다. 하지만, Telnet 데몬을 사용하지 않는다면, 이 취약점에는 안전합니다.
FreeBSD 홈페이지에는 이미 패치가 올라와 있습니다. 이를 이용하여 패치할 수 있습니다.
http://security.freebsd.org/patches/SA-09:05/telnetd.patch


2. 참고 문헌 및 사이트
Exploit 소스 : http://www.milw0rm.com/exploits/8055 [Exploit 코드 부문 자체 수정이 있었습니다.]
공식 권고문 : http://security.freebsd.org/advisories/FreeBSD-SA-09:05.telnetd.asc
공식 패치 코드 : http://security.freebsd.org/patches/SA-09:05/telnetd.patch



[indra (indra@a3security.com) 의 한마디...]
LD_PRELOAD는 *nix 계열 environment 에서 동적 라이브러리를 로드하는데에 쓰이며, 이는 다른 라이브러리를 로딩하는 로직보다 우선순위를 가지고 있습니다.
따라서 예전에 함수의 반환값을 0으로 만드는 라이브러리를 LD_PRELOAD를 사용해 로드하고 shell을 실행하면 getuid() 계열 함수의 반환값이 0 이 되어 whoami, id 등의 명령어 결과를 root 로 만들게끔 조작하는 것이 가능했었습니다.

그러나 실제 kernel 상의 process image에는 권한등록이 일반 user로 되어 있기 때문에 실제 root의 권한은 아니었고요. 이러한 LD_PRELOAD의 기능을 이용한 것이 해당 exploit의 기본 아이디어 이구요.

원격접속을 받아 인증을 하고 pts, tty 등의 터미널 관련 device를 생성하는 등의 작업을 하기 위해서는 root 권한으로 daemon이 실행되어야 하는데, LD_PRELOAD 를 이용한 로드된 라이브러리에서 shell을 바로 실행시켜 버리기 때문에 권한이 낮춰지지 않은 상태의 root shell이 실행되게 됩니다.

exploit 은 현재 공개되어 있으며, 09년 2월 16일자로 공개되었습니다.

다음의 링크 입니다.

http://milw0rm.com/exploits/8055

exploit을 보면 environ 명령을 통해 환경변수를 설정할 수 있고, 이를 조작하여 원격접속 시 LD_PRELOAD라는 환경변수를 이용해 악의적인 라이브러리를 로드할 수 있게 됩니다.어떻게 보면 예전에 나왔던 SunOS telnet 취약점이랑 비슷합니다. remote 취약점은 아니나, web, ftp 에 접근하여 파일을 생성할 수 있는 경우 해당 취약점에 노출됩니다.

이에 대한 공식 권고문은 다음의 링크 입니다.

http://security.freebsd.org/advisories/FreeBSD-SA-09:05.telnetd.asc

공식 패치의 코드는 다음의 링크 입니다.

http://security.freebsd.org/patches/SA-09:05/telnetd.patch

패치된 코드는 환경변수를 의미하는 environ을 설정하고 환경변수가 등록되어 있으면 해당 값을 지워버리는 것으로 LD_PRELOAD의 환경변수 값을 지워버리게 됩니다. 따라서 공격자의 라이브러리는 로드되지 않겠죠.



Copyright(c) 1998-2009 A3 Security ,LTD


Disclaimer
※ 현재 ㈜에이쓰리시큐리티에서 테스트 및 분석 중에 있으며, 이 문서는 계속 업데이트될 것입니다. 본 문서는 보안취약점으로 인한 피해를 최소화하는 데 도움이 되고자 작성되었으나, 본 문서에 포함된 대응방안의 유효성이나 기타 예상치 못한 시스템의 오작동 발생에 대하여서는 ㈜에이쓰리시큐리티에서는 일체의 책임을 지지 아니합니다.