# CVE Number :CVE-2013-3893
# MS Advisory :MS13-086
# 취약점 종류 :IE Use-After-Free 코드 실행 취약점
* 유사한 Use-After-Free 취약점 분석은 이전에 올려진 CVE-2013-1347, CVE-2012-4792, CVE-2012-4969 등의 글을 참고한다.
취약점원인(PoC) 분석
Use-After-Free 취약점은 이미 해제된 메모리를 참조하는 것으로 인하여 발생하는 취약점이다.
따라서, 취약점 분석은 원인이 되는 메모리의 생성(Create), 해제(Free), 참조(Use) 흐름을 분석한다.
본 분석에서는 Windbg 디버거와 GFlag 를 사용한다.
[그림] 취약점 PoC코드
해당 PoC 코드를 디버거를 이용하여 실행해보면 다음과 메모리 참조 오류로 인하여 크래쉬가 발생한다.
이때, GFlag 설정을 통해 해제된 메모리의 Call Stack을 참고하면, 분석 시나리오를 설계할 때 BreakPoint(BP) 지점의 힌트를 얻을 수 있다.
mshtml!CTreeNode::GetInterface+0xac:
63662dc0 8b08 movecx,dwordptr [eax] ds:0023:f0f0f0f0=????????
>!heap –p –a 0033a320
address 0033a320 found in
_HEAP @ 250000
HEAP_ENTRY Size Prev Flags UserPtrUserSize – state
0033a2f8 0011 0000 [03] 0033a320 0004c – (free DelayedFree)
7c97bc4c ntdll!RtlFreeHeapSlowly+0x00000037
7c957573 ntdll!RtlFreeHeap+0x000000f9
63625834 mshtml!CTreeNode::Release+0x0000002d
636266b2 mshtml!CMarkup::UnloadContents+0x00000381
… 중간 생략 …
63751297 mshtml!COmWindowProxy::SwitchMarkup+0x0000059f
637525ff mshtml!CDocument::open+0x00000417
637561c5 mshtml!CDocument::write+0x0000007c
>>개체 생성(Create)<<
원인이 되는 메모리번지 0033a320는 실제 참조에 앞서, 다음과 같이mshtml!CTreeNode::CTreeNode() 클래스 생성자를 통해서 생성된다.
실제 Windbg에서 찍어본 로그 정보를 통해 할당된 메모리에는 mshtml!CBodyElement::`vftable’ 정보를 담고 있는 것을 확인할 수 있다.
> Create CTreeNode at 0033a320
>0033a320 0495b288 635ba8c0 mshtml!CBodyElement::`vftable’
정상적인 경우, 이렇게 생성된 메모리는 해당 메모리에 담긴 vtable을 참조해서 Function을 호출하기 위한 다음 코드에서 참조가 이루어진다.
> Reference 6360fdf6
eax=0495b288 ex=0033a320 ecx=635ba8c0 edx=03b7fb7c esi=636397e4 edi=63662c78eip=63662dca esp=03b7fb5c ebp=03b7fb80
mshtml!CTreeNode::GetInterface+0xb6:
63662dca ff11 call dwordptr [ecx] ds:0023:635ba8c0={mshtml!CBodyElement::PrivateQueryInterface (6360fdf6)}
>>개체 해제(Free)<<
앞서 Call Stack 에서 확인된 바대로, 다음 스크립트 코드를 만나면 해당 개체가 존재하는 메모리 번지가 해제된다.
id_0.onlosecapture=function(e){
document.write(“”);
}
실제 해당 메모리가 해제되는 지 전/후의 디버그 로그를 통해 확인해보자.
> Before Free 0033a320 ( 메모리 해제 전 )
>0033a320 0495b288 635ba8c0 mshtml!CBodyElement::`vftable’
eax=00000000 ebx=00000000 ecx=00000000 edx=0033a320esi=0495b288 edi=0033a320eip=63625825 esp=03b7de64 ebp=03b7dec4
mshtml!CTreeNode::Release+0x1e:
63625825 52 pushedx
> After Free 0033a320 ( 메모리 해제 후 )
>0033a320 f0f0f0f0
eax=00000001 ebx=00000000 ecx=7c94005d edx=00155000 esi=0495b288 edi=0033a320eip=63625834 esp=03b7de64 ebp=03b7dec4
mshtml!CTreeNode::Release+0x2d:
63625834 33c0 xoreax,eax
>>개체 참조(Use)<<
이렇게 이미 해제되어 버린 메모리를 정상적인 경우처럼 참조하기 때문에 다음과 같이 메모리 참조 오류가 발생한다.
eax=f0f0f0f0 ebx=0033a320ecx=00000003 edx=00000000 esi=636397e4 edi=63662c78eip=63662dc0 esp=03b7ef08 ebp=03b7ef20
mshtml!CTreeNode::GetInterface+0xac:
63662dc0 8b08 movecx,dwordptr [eax] ds:0023:f0f0f0f0=????????
지금까지는 POC를 통해서 취약점 발생 부분을 분석해보았다.
이제 특별한 코드를 추가해서 사용자 입력을 통해 프로그램 흐름(EIP)을 변경할 수 있는 지 확인해보자.
>>EIP 변경 코드 <<
변경된 코드를 다시 실행해 보면, 해제된 메모리 부분에 삽입된 코드로 인하여 새로운 개체가 생성되어 재사용 되는 것을 확인할 수 있다.
> Create CTreeNode at 049ecee8
049ecee8 049ece80 635ba8c0 mshtml!CBodyElement::`vftable’
> Before Free 049ecee8
049ecee8 049ece80 635ba8c0 mshtml!CBodyElement::`vftable’
> After Free 049ecee8
049ecee8 f0f0f0f0
>Alloc 049ecee8
049ecee8 635c0ad0 636170bb mshtml!CDivElement::PrivateQueryInterface
> Reference 8b55ff8b
eax=635c0ad0 ebx=049ecee8ecx=636170bb edx=03b7ef1c esi=636397e4 edi=63662c78eip=63662dca esp=03b7eefc ebp=03b7ef20
mshtml!CTreeNode::GetInterface+0xb6:
63662dca ff11 call dwordptr [ecx]ds:0023:636170bb=8bff558b
(8fc.aa0): Access violation – code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=635c0ad0 ebx=049ecee8 ecx=636170bb edx=03b7ef1c esi=636397e4 edi=63662c78eip=8b55ff8b esp=03b7eef8 ebp=03b7ef20
8b55ff8b ?? ???
삽입된 코드로 인하여 최종적으로 호출되는 CALL의 지점이 변경되는 것을 알 수 있다.
이때, 이미 해제된 메모리는 재사용되어 다음과 같이 Free 가 아닌 Busy 상태이다.
>!heap -p -a 049ecee8
address 049ecee8 found in
_HEAP @ 250000
HEAP_ENTRY Size Prev Flags UserPtrUserSize – state
049ecec0 000c 0000 [03] 049ecee8 00028 – (busy)mshtml!CDivElement::`vftable’
7c97b394 ntdll!RtlAllocateHeapSlowly+0x00000044
7c948f21 ntdll!RtlAllocateHeap+0x00000e64
635c0a9c mshtml!CDivElement::CreateElement+0x00000016
635a67f5 mshtml!CreateElement+0x00000043
…
자, 이제 사용자 입력을 통해 프로그램 흐름(EIP)을 변경할 수 있다는 확인하였다.
실제 일본과 대만을 타겟으로 한 공격코드(Exploit)에서는 참조하는 메모리를 12121202 로 맞추고, 힙스프레이 코드를 통해 메모리 상에 올려진 페이로드(Payload)를 실행하도록 구성되어 있다.
공격코드(Exploit) 분석
해당 공격코드는 시스템 환경을 체크해서 Windows XP와 Windows 7에서 동작한다.
단, Windows 7의 경우, Office 버전이 존재하지 않으면 실행하지 않는다.
-
브라우저 버전(IE)
-
오피스 버전 (Windows 7의 경우, 페이로드 선택에 사용)
-
플랫폼 (Windows)
-
언어 (페이로드 선택에 사용)
공격코드에서는 다양한 언어, 플랫폼, 오피스 등의 조건에 맞게 ROP 가젯(gadget)과 쉘코드(shellocde)로 구성된 페이로드를 선택하여 힙 스프레이 기술을 이용하여 메모리 상에서 로드한다. ( function init() )
취약점이 발생하고 실제 페이로드(Payload)로 점프하는 코드는 다음이다.
ECX = 12121202
EAX = [ECX] = 12121212
EDX = [EAX+70h] = [12121212+70] = [12121282] = 77bc5ed5
77bc5ed5 의 코드를 실행하고 나면 다음과 같이 CALL 스택이 페이로드쪽으로 변경되면서, 이후 순차적으로 ROP 가젯의 코드를 수행하게 된다.
최종적으로, 사용된 쉘코드는 악성코드를 특정 사이트에서 다운로드하여 실행(c:Documents and SettingsvmuserLocal SettingsTemprunrun.ex)한다.
— 끝 —