Internet Explorer wininet.dll URL parsing memory corruption details

Type securityvulns
Reporter Securityvulns
Modified 2005-04-14T00:00:00


Vendor: Microsoft Software: Internet Explorer 6.0, 5.5, 5.01 Problem: Memory corruption, code execution Remote: Yes Risk Level: Medium to low (hard to exploit) Authors: Axle (ICQ 755756) bug discovery 3APA3A, bug research Original URL:


Axle (ICQ 755756) found an interesting and hard to catch bug in InternetCreateUrlW function of wininet.dll. It's hard to find, because in most cases vulnerable application doesn't crash and it can not be found with automated code scanner, because it's not typical buffer overflow, but the bug in program logic. Buffer length is checked, but because of mistyping in vulnerable code it fails to handle exceptional conditions. Vulnerable piece of code is located at address 0x771E8E85 (wininet.dll version 6.00.2900.2180).

This part of code should convert hostname from Unicode. Whole process is:

  1. Calculate size of target buffer (exactly twice more than actually required to make you buy additional memory).
  2. Allocate buffer with LocalAlloc()
  3. Copy string to target buffer with WideCharToMultiByte()
  4. NULL-terminate target string, which is already NULL terminated to add additional CPU cycles. It's required to make you buy faster processor.

It clearly confirms Microsoft has contract with Intel. Joke. Probably.

If translate to C this code looks like

/ 771E8E85 / if (stringlen == 0) {/ handle exceptional conditions /} / the bug is here. It should be stringlen <= 0 / else { ... / stringlen is -1 on oversized hostname / buflen = (stringlen)2 + 2 / buflen is 0 / buf = LocalAlloc(0, buflen); / because LMEM_MOVEABLE is not set LocalAlloc returns zero size page from heap/ / 771E8EC1 / len = WideCharToMultiByte (0, 0x400, pointer_to_hostname, -1 / NULL terminated/, buf, buflen / size of allocated buf /, NULL, 0); / because cbMultiByte is 0 WideCharToMultiByte simply calculates required length, it's equal to real length of our hostname, it doesn't change content of memory pointed by buf) /

 /* 771E8EC6 */
 buf[len]  =  0;  /*  here 0 is written to some unallocated memory and we can
                 partially control address by the length of our hostname */

... }

The problem is on oversized hostname, because stringlen is -1, not 0 as expected. So we have:

  1. Calculated buffer size is 0.
  2. LocalAlloc returns valid pointer to empty chunk.
  3. Because targed buffer is empty, WideCharToMultiByte() does not actually copies any data, but only calculates length of hostname string.
  4. As a result we can write single '\0' byte to partially controllable (with hostname length) location.

Because translated hostname points to empty memory chunk it contains some garbage. In most cases it's only visible effect (you see garbage in address bar of Internet Explorer). In rare cases than empty chunk is at the end of memory page on the heap Internet Explorer crashes.


<a href='http://<buffer_of_256-300_bytes>/'>TEST (CLICK)</a>

Theoretically, this bug is exploitable, because we can manipulate with memory chunks allocating, e.g. with Javascript or page redirections. In practice it's very hard for lazy person.

References: 1. Multiple Microsoft Internet Explorer memory corruptions 2. Microsoft Security Bulletin MS05-020 Cumulative Security Update for Internet Explorer (890923) 3. URL Parsing Memory Corruption Vulnerability 4. Microsoft Windows Internet Explorer Long Hostname Heap Corruption Vulnerability

-- /\_/\ { , . } |\ +--oQQo->{ ^ }<-----+ \ | ZARAZA U 3APA3A } You know my name - look up my number (The Beatles) +-------------o66o--+ / |/