y0u_bat
GHOST: glibc gethostbyname buffer overflow 번역 목차 (2/6) 본문
발번역입니다...
원문: http://www.openwall.com/lists/oss-security/2015/01/27/9
--[ 목차 ]---------------------------------------------------------------- 1 - 서론 2 - 분석 3 - 정상 침작 요인 (Mitigating factors) 4 - 취약점 존재여부 및 사례 연구 5 - 공격 6 - 결론
--[ 1 - 서론 ]-------------------------------------------------------------
Qualys에서 내부 코드에 대해 검사를 하는 동안, 우리는 GNU C 라이브러리인 glibc안에 __nss_hostname_digits_dots() 함수 내부에서 버퍼 오버플로우가 발견했다.
이버그는 gethostbyname *() 함수의 내부의 가까이 존재하고 있다. 그래서 우리는 gethostbyname을 분석하기로 결정하였다.
그리고 이것은 엄청 영향이 있었다. 이 취약점에 이름을 "GHOST" 라고 한다.
중심내용:
- gethostbyname() 과 gethostbyname2() 를 통해서 힙영역 버퍼에 오버플로우가 가능하며,
gethostbyname_r() 혹은 gethostbyname2_r() 는 사용자가 제공하는 버퍼를 덮을 쓸 수 있다.
- sizeof(char *) 바이트만큼 덮어 쓸 수 있다. (32비트 운영체제 경우엔 4바이트, 64바이트 운영체제 경우엔 8바이트)
해당내용은 오직 숫자 0~9, 점(.)으로 되어 있어야 한다. 그리고 끝은 null로 되어 있어야 된다.
- 이런 제한에도 불구하고, 임의적인 코드를 실행하는데 성공하였다. 우리는 개발된 Exim 메일서버를 리모트 공격에 하는데 있어 불리하게 하는 기존의 보호기법 ( aslr, pie, nx) 을 32비트 운영체제와 64비트 운영체제 둘다 우회 가능함을 증명 할 수 있다.
우리는 조만간에 메타스플로잇 모듈에 우리의 익스플로잇을 발표 할 것입니다.
- 첫번째로 취약한 버전은 GNU C 라이브러리의 glibc-2.2 릴리즈 2000.11.10 이다
- 우리는 확인된 취약점은 이버그의 영향을 완화시킨다.
특히, 우리가 발견한 저 취약점은 2013년 5월 21일에 패치되었다. ( gdblic-2.17 ~ glibc-2.18 )
불행하게도 이것은 보안위혐이 알려지지 않았다. 결과적으로 매우 안정적이며, 오랜기간 노출되어 배포됬다.
(여전히 영향받는 버전: 데비안7, 레드헷 기업용 리눅스 6 & 7, 센토스 6 & 7, 우분투 12.04)
--[ 2 - 분석 ]------------------------------------------------------------
그 취약한 함수 __nss_hostname_digits_dots()는 내부적으로 glibc의 nss/getXXbyYY.c 와 nss/getXXbyYY_r.c을 호출한다.
그러나 그 호출들은 #ifdef HANDLE_DIGITS_DOTS 매크로 정의가 되어있다.
해당 매크로 정의하고 있는 파일
- inet/gethstbynm.c
- inet/gethstbynm2.c
- inet/gethstbynm_r.c
- inet/gethstbynm2_r.c
- nscd/gethstbynm3_r.c
그 파일들은 gethostbyname* () 류의 함수를 실행한다. 이런 이유로 오직 __nss_hostname_digits_dots()에서 일어나는 버퍼오버플로우가 유일한 방법이다.
이코드는 glibc-2.17 이다:
35 int 36 __nss_hostname_digits_dots (const char *name, struct hostent *resbuf, 37 char **buffer, size_t *buffer_size, 38 size_t buflen, struct hostent **result, 39 enum nss_status *status, int af, int *h_errnop) 40 { .. 57 if (isdigit (name[0]) || isxdigit (name[0]) || name[0] == ':') 58 { 59 const char *cp; 60 char *hostname; 61 typedef unsigned char host_addr_t[16]; 62 host_addr_t *host_addr; 63 typedef char *host_addr_list_t[2]; 64 host_addr_list_t *h_addr_ptrs; 65 char **h_alias_ptr; 66 size_t size_needed; .. 85 size_needed = (sizeof (*host_addr) 86 + sizeof (*h_addr_ptrs) + strlen (name) + 1); 87 88 if (buffer_size == NULL) 89 { 90 if (buflen < size_needed) 91 { .. 95 goto done; 96 } 97 } 98 else if (buffer_size != NULL && *buffer_size < size_needed) 99 { 100 char *new_buf; 101 *buffer_size = size_needed; 102 new_buf = (char *) realloc (*buffer, *buffer_size); 103 104 if (new_buf == NULL) 105 { ... 114 goto done; 115 } 116 *buffer = new_buf; 117 } ... 121 host_addr = (host_addr_t *) *buffer; 122 h_addr_ptrs = (host_addr_list_t *) 123 ((char *) host_addr + sizeof (*host_addr)); 124 h_alias_ptr = (char **) ((char *) h_addr_ptrs + sizeof (*h_addr_ptrs)); 125 hostname = (char *) h_alias_ptr + sizeof (*h_alias_ptr); 126 127 if (isdigit (name[0])) 128 { 129 for (cp = name;; ++cp) 130 { 131 if (*cp == '\0') 132 { 133 int ok; 134 135 if (*--cp == '.') 136 break; ... 142 if (af == AF_INET) 143 ok = __inet_aton (name, (struct in_addr *) host_addr); 144 else 145 { 146 assert (af == AF_INET6); 147 ok = inet_pton (af, name, host_addr) > 0; 148 } 149 if (! ok) 150 { ... 154 goto done; 155 } 156 157 resbuf->h_name = strcpy (hostname, name); ... 194 goto done; 195 } 196 197 if (!isdigit (*cp) && *cp != '.') 198 break; 199 } 200 }
121~125라인을 보면 host_addr, h_addr_ptrs, h_alias_ptr,hostname 4개의 포인터를 준비한다.
size_needed을 계산할때sizeof(*h_alias_ptr) 만큼 빼먹은 실수가 있다.
그러므로 157라인에서 strcpy()할때 버퍼를 32비트운영체제 경우 4바이트, 64비트 운영체제 경우 8바이트를 오버플로우 시킬수있다.
오버플로우를 하기 위한 조건
- 첫번째 문자열이 숫자여야 된다. (라인127)
- 마지막 문자열이 점이면 안된다. (라인135)
- 오직숫자와 점으로 구성되야 된다.
- 오버플로우 할 버퍼가 충분이 거야 된다. 예를 들어, gethostbyname() 함수는 처음에 버퍼에 1024만큼 malloc 해준다.
- inet_athon() 함수에서 성공적으로 IPv4 주소가 성공적으로 파싱되야 된다.
'System' 카테고리의 다른 글
CVE-2015-0235 GHOST 취약점 (0) | 2016.02.16 |
---|---|
SROP - Sigretrun Oriented Programming (0) | 2016.02.11 |
[S.S.A] 시스템해킹 스터디 6주차 (pintool) (0) | 2015.11.22 |
[SSA] 시스템 스터디 3주차 (0) | 2015.10.20 |
[SSA] 시스템 스터디 1주차 정리(어셈블리) (1) | 2015.10.06 |