IE 7 XML 제로데이 취약점 분석
이 글은 H.D.Moore의 IE 7 XML 제로데이 취약점 분석 글을 번역한 것입니다.
이번 분석을 위해 2개의 샘플을 입수했습니다. 익스플로잇은 3부분으로 나누어 볼 수 있습니다.
첫번째 부분은 3개의 함수로 이루어져 있습니다. 첫번째 함수는 sleep() 호출과 동일한 기능을 제공합니다. 두번째 함수는 일반적인 기법을 이용해서 프로세스 힙에 문자열을 뿌립니다. 세번째 함수는 특정 길이의 문자열을 반환하는 기능을 가지고 있는데, 두번째 함수에서 이 함수를 사용합니다.
두번째 부분은 쉘코드입니다. 여기에서 자세한 내용을 언급하지는 않겠지만, 이 쉘코드는 윈도우 실행 파일을 다운로드합니다.
세번째 부분은 취약점을 공격하는 부분입니다. 잡다한 코드를 제거하고 나면 아래와 같이 정리할 수 있습니다.
<XML ID=I><X><C>
<![CDATA[
<image SRC=http://ਊਊ.AAAAA.lan
SRC=http://BBBB.lan >
]]>
</C></X></XML>
<SPAN DATASRC=#I DATAFLD=C DATAFORMATAS=HTML>
<XML ID=I> </XML>
<SPAN DATASRC=#I DATAFLD=C DATAFORMATAS=HTML></SPAN>
</SPAN>
버그는 두 개의 SPAN 태그에 의존합니다. 첫번째 SPAN 태그는 인터넷 익스플로러에게 XML 문서 내의 데이터를 HTML로 포맷팅하라고 지시합니다. 두번째 SPAN 태그는 첫번째 SPAN 태그와 동일하지만 첫번째 SPAN 태그 안에 들어있습니다. 이로 인해 힙 손상이 발생하면서 첫번째 <image> SRC 속성의 호스트 이름의 첫 4바이트로 객체 포인터를 덮어쓰게 됩니다. 인터넷 익스플로러는 호스트 이름의 유니코드 문자를 2바이트 값으로 확장하는데, 결과적으로 객체 포인터를 덮어쓰면서 총 4바이트를 제어할 수 있게 됩니다. 위의 예에서는 ਊ을 골랐는데 이는 16진수로 0x0a0a입니다. 이 값이 32비트 포인터로 확장되면서 0x0a0a0a0a가 됩니다. 이 값은 접근성이 좋기 때문에 브라우저 힙 오버플로우에 자주 사용됩니다.
자, 이제 원래 익스플로잇 코드를 다시 보겠습니다. 익스플로잇 코드에서는 \x0a\x0a\x0a\x0a가 길게 반복되고 끝부분에 쉘 코드가 붙어있는 거대한 문자열을 볼 수 있습니다. 이 코드는 브라우저가 많은 메모리를 할당시킨 다음 0x0a0a0a0a 프로세스 주소에 \x0a\x0a\x0a\x0a 문자열을 가득 채우도록 유도합니다. 메모리에 이 문자열을 채워넣은 다음 익스플로잇은 sleep() 함수를 이용해서 6초를 대기합니다. 다시 깨어난 다음, 익스플로잇은 document.write() 메소드를 이용해서 XML/SPAN 코드를 웹 페이지에 쏟아붓습니다. 브라우저가 이 코드를 렌더링하려고 할 때 힙 손상 버그가 발생하면서 객체 포인터를 덮어 쓰고, 그 다음 해당 객체의 메소드를 호출하게 됩니다. 그 결과 아래와 같은 어셈블리 코드를 실행하게 됩니다:
mov ecx,dword ptr[eax]
push edi
push eax
call dword ptr[ecx+84h]
이 코드를 실행하는 시점에서 EAX 레지스터 값은 0x0a0a0a0a입니다. 이 레지스터는 객체를 가리키는 포인터를 저장하고 있는데, 이게 익스플로잇이 첫번째 <image> 태그의 SRC 속성 내부에 포함된 유니코드 문자로 덮어쓰이게 됩니다. 위 코드의 첫번째 인스트럭션은 eax 주소가 가리키는 4바이트 데이터를 읽어서 ecx 레지스터에 저장합니다. 이전에 브라우저가 커다란 메모리를 할당한 후 0x0a 문자열을 채우도록 했기 때문에, ecx 레지스터는 0x0a0a0a0a로 설정됩니다. 이제 브라우저는 edi와 eax 레짓터를 스택에 넣고, ecx+0x84 위치의 포인터를 읽고 호출합니다. ecx가 0x0a0a0a0a이므로 ecx+0x84는 0x0a0a0a8e를 가리키게 됩니다. 0x0a0a0a8e는 0x0a 문자와 쉘코드로 끝나는 거대한 문자열을 가리키게 됩니다.
이제 브라우저는 0x0a 문자로 구성된 문자열을 실행합니다. 0x0a를 x86 인스트럭션으로 해석하면 "or cl,[edx]"입니다. 그러므로 인스트럭션을 실행하면 edx 레지스터가 가리키는 데이터를 읽은 다음 이 값을 ecx 레지스터의 하위 8비트(cl)와 OR 연산합니다. edx 레지스터는 읽기 가능한 메모리를 가리키므로 사실상 아무런 일도 하지 않는 인스트럭션을 문자열 끝까지 계속 실행합니다. 문자열 끝 부분에는 쉘 코드가 붙어있으므로 익스플로잇은 취약점을 이용하여 쉘 코드를 실행할 수 있게 됩니다. 이 쉘 코드는 외부에서 윈도우 실행 파일을 다운로드 받아 실행하는 일을 수행합니다. 객체 포인터/힙 스프레이 기법은 인터넷 익스플로러에서 힙 손성 취약점을 익스플로잇할 때 흔히 사용됩니다. 그래서 이런 부류의 취약점은 대부분 긴급 등급으로 분류됩니다.
이 취약점을 익스플로잇 하려면 2개의 조건을 만족시켜야 합니다. 하나는 인스트럭션 포인터(IP)가 쉘 코드 위치를 가리키도록 만들 수 있어야 한다는 것이고, 나머지 하나는 인스트럭션 포인터를 설정한 다음 쉘 코드를 실행할 수 있어야 한다는 것입니다. 첫번째 조건은 알려진 위치에 메모리를 할당하고 임의의 내용을 채워넣을 수 있는 것으로 해결할 수 있습니다. 만약 메모리가 할당되는 위치를 정확히 제어할 수 있다면, 쓸데없이 nop sled를 만들 필요가 없습니다. 두번째 조건은 운영체제와 설정, 하드웨어에 따라 영향을 받습니다. 브라우저 익스플로잇을 언급하는 많은 문서에서는 사용자에게 데이터 실행 방지(DEP)를 활성화 하라고 권고합니다. 데이터 실행 방지가 활성화되어 있으면 데이터로 간주되는 메모리 영역에서 쉘 코드를 실행할 수 없게 됩니다. 하지만 데이터 실행 방지 기능은 인터넷 익스플로러 6과 7에서 기본적으로 활성화되어 있지 않기 때문에 손쉬운 목표가 될 수 있습니다.
인터넷 익스플로러 6의 경우에는 Alexander Sotirov 씨가 개발한 heapLib 자바스크립트 라이브러리를 사용해서 첫번째 조건을 쉽게 만족시킬 수 있습니다. 이 라이브러리는 예측 가능한 위치에 가짜 vtable을 할당하는 API를 제공합니다. 따라서 인터넷 익스플로러 6을 목표로 한 경우에는 힙 스프레이나 nop sled가 필요하지 않습니다. 인터넷 익스플로러 7에서는 가짜 vtable이 파기되는 것으로 보이는 문제가 있긴 하지만, 그런대로 쓸만합니다.
두번째 문제를 해결하려면 DEP를 우회해야 하고, 윈도우 비스타나 서버 2008에서 사용되는 NX나 ASLR 같은 보호를 무력화해야 합니다. 블랙햇 USA 2008 컨퍼런스에서 Alexander Sotirov와 Mark Dowd가 발표한 How to Impress Girls with Browser Memory Protection Bypasses는 보호 기법에 관계없이 잘 실행되는 브라우저 익스플로잇을 제작하는 법을 다루고 있습니다. 이 기법과 관련 논문을 읽어보면 비스타처럼 ASLR을 강제하는 운영체제에서도 이런 류의 취약점을 안정적으로 익스플로잇할 수 있습니다.
by xeraph | 2008-12-12 16:00:12 | 미분류 | 트랙백 (1) | 덧글 (0)
Tracked from nchovy's me2DAY 2008-12-12 16:14:58
IE 7 XML 제로데이 취약점 분석, HDM의 IE7 XML 익스플로잇 분석 글을 번역한 것입니다.




