a brief history of ie vulnerability attack and defense

Posted by lipsius at 2020-03-06

In this paper, the influence of Microsoft IE browser in the history is reviewed, the evolution of IE vulnerability in attack defense technology is discussed, and the historical experience and footprints of confrontation left by people before such vulnerability are recorded. In the Internet Explorer attack and defense has entered the third stage, the author just entered the study of Internet Explorer attack and defense. Now code 'project Spartan's Microsoft's edge browser took over the burden of windows default browser from ie11, which made the historical large version of IE browser freeze frame 11, which has been in service for nearly 20 years, consciously have a brief note of the historical research of IE browser vulnerability, which can be used as a reference for later novice security researchers. Therefore, it is inevitable to make omissions in this article. Please correct it.

Update record

January 8, 2016 - first draft

Background of browser vulnerability research

In recent years, part of the focus of network security research began to incline from PC end to mobile end. However, in the research of PC security, ie / Chrome / Firefox / Spartan and Adobe's reader / acrobat / flash series are still used as the depth of technology research. Of course, there are also some file format vulnerabilities for targeted attacks in specific regions, which are also the focus of some hackers, such as iciaro, a popular word processing software in Japan, hancom office and WPS.

Since its birth, browser mainly provides simple document reading function, rarely constitutes a threat to network security, but with the rapid development of Internet, more and more function sets are added to the browser. The browser not only needs to provide the basis for traditional computer applications such as reading documents, watching movies and listening to music, but also needs to provide support for emerging Internet applications such as social networks and online shopping. Browser brings more security problems when it adds feature set. And the IE browser integrated and bundled in the system can occupy a large share of the market, which has naturally become the target of public criticism. In this case, the attack and defense arms race against IE browser has begun.

II. Several times of IE browser vulnerability attack and defense

1.1 buffer overflow and ActiveX control era (2003-2008)

This is a stage from 2003 to 2008. In this stage, ie vulnerabilities are mainly caused by ActiveX controls, stack overflow and some simple heap overflow vulnerabilities. For example, buffer overflow caused by a single overlong SRC attribute of iframe tag and similar stack overflow vulnerabilities.

In the earlier stage, the conventional fuzzy method, whether based on deformation or generation, is more suitable for the application of binary format flow data, especially those files or network protocol formats containing a large number of C language structure types. Because the format parsing code often uses the data stream data as the parameter of memory operation without checking, the single point of deformity is often enough to trigger the possible processing vulnerabilities in the parsing code: buffer overflow caused by extra long data, integer overflow and underflow caused by malformed value, array overrun access caused by malformed index value, excessive memory read-write operation caused by malformed count Do. For buffer overflow caused by overlong data, the sample structure is relatively simple and the overlong value is passed in. So this type of vulnerability is relatively simple to explore.

The history of the early ie 0day vulnerability is simply reviewed, only including the more influential examples (Figure 1.1.1, figure 1.1.2). Some vulnerabilities may not be the problem of IE itself, but ie is the most important utilization channel.

Figure 1.1.1

Figure 1.1.2

1.2 time keywords

Protection Party: dep / ASLR / stack cookie

Attacker: stack overflow / simple heap overflow / ROP / heapspray

A buffer overflow also gives a simple example about buffer overflow for easy understanding. (Fig. 1.2.1)

Figure 1.2.1 we compile the above program in the compiler of vc6.0, and the results are as follows. (Figure 1.2.2)

Figure 1.2.2

You can see that the main function only calls foo. But in practice, the bar function is also called.

In fact, due to improper handling of foo function and long external input, the return address of foo() function is modified after buffer overflow, resulting in the program executing the bar() function that should not have been executed. And if the covered return address is a series of carefully encoded shellcodes with backdoor function, then the computer can be controlled by a malicious attacker.

This is just an example of a simple C program, which is different in the form of browsers. For example, the iframe tag supported by IE browser, and the single super long SRC attribute of iframe tag to construct super long data may lead to buffer overflow and browser crash.

Dep and security cookies

From the above buffer overflow, we can see that in a specific environment, as long as the control input data is too long and then the return address is overwritten, as long as the program crashes at this time, it is easy to sense that the target program has a buffer overflow vulnerability. Then we can execute our malicious code by modifying the super long data and combining the appropriate shellcode to accurately cover the return address. It's just a very short time for the attacker. Microsoft started to provide dep support from Windows XP SP2. The full name of DEP is data execution prevention, which can be divided into hardware dep and software Dep. But the goals are the same. Block code execution on data pages. (Figure 1.2.3)

(Fig. 1.2.3)

Since the memory page where the data is located is marked as non executable, even if the program overflows and successfully transfers into the execution of shellcode, the CPU will throw an exception to prevent the execution of malicious shellcode.

It can also be seen here that the attacker at this stage only covers the return address on the stack and tries to execute the malicious shellcode from the stack.

Considering that the attack was caused by overwriting the return address, Microsoft added a compiler option gs to VS2008 and later compilers. That is, security cookies can also be called stack cookies. (Fig. 1.2.4)

(Fig. 1.2.4)

(Fig. 1.2.5)

You can see that a security_cookie is written to the stack in advance at the beginning. Before the function returns, it will check whether the security_cookie has been tampered with. (Fig. 1.2.5)

Once tampered with, it will jump to the abnormal execution process. (Fig. 1.2.6)

(Fig. 1.2.6)

Of course, this is about the stack. There are similar protections in heap overflow, such as header cookie.

Focus on SEH

When the attacker found that the threshold of covering 4-byte return address (32-bit system) to execute shellcode was raised, he came up with a new scheme. Override the exception handler of SEH

In fact, all efforts in binary attack and defense are to get even one chance to control EIP (RIP). And sEH just meets this requirement can provide the attacker with this opportunity. The sEH is stored in the stack, so the extra long data may overwrite the sEH, where the entry address of the exception handling function is changed to the start address of shellcode. Because the error data generated after overflow often triggers exceptions, and shellcode can get an opportunity to be pointed by EIP at this time.

But the good time for the attacker is still very short. The / safeseh option is supported in VS2003 (. Net) in response to attacks against sEH. Later, SEOP was further launched. Of course, these measures need the cooperation of XP SP2 operating system, updated operating system and Dep. These two kinds of protective measures will take up a lot of space. Interested readers can learn by themselves.

It should be noted that the 64 bit windows system sEH is no longer on the stack. It is impossible to exploit the vulnerability by overwriting the exception handling routine with stack overflow.

ROP ASLR and heapspray Technology

As mentioned earlier, DEP will prevent shellcode from executing even if the return address is overwritten by shellcode. However, if the executed code is a function provided by the operating system library itself, such as directly using the system() function provided in the libc library to override the return address of the program function call. Then pass the reset parameter so that it can execute as expected. This way of bypassing dep is called return to libc

The return to libc attack uses the address of the library function to override the return address of the program function call, so that the library function can be called when the program returns, so that the attack can be successfully implemented. However, because the instruction sequence available to the attacker can only be a function that already exists in the application, the attack ability of this attack mode is limited. And the attack can only be implemented in x86 CPU platform, but not in x86 CPU platform. This is because in x86 CPU platform, program execution parameters are not passed through the stack but through registers, and return into libc needs to pass parameters through the stack.

Because of the limitations of this return to libc attack, return oriented programming (ROP) has been proposed and become an effective return to libc attack. The way of return oriented programming attack is no longer limited to jump the control flow of the vulnerable program into the library function, but can use a set of instruction sequences identified and selected from the program and the library function. The attacker concatenates these instruction sequences to form the shellcode needed by the attack to conduct subsequent attacks. Therefore, this method still does not need to inject new instructions into the vulnerable program to complete any operation. At the same time, it does not take advantage of complete library functions, and therefore does not rely on passing parameters through the stack when a function is called.

Generally, we extract the instruction sequence of ROP to construct ROP chain through immunitydbg and Mona script plug-in

ROP chain display (Figure 1.2.7)

Figure 1.2.7

At one time, the emergence of ROP made attackers in the era of XP prevail. Because the DLL load address is fixed. The work of extracting ROP chain from different versions of IE is boring, but the attack effect is good. But Microsoft, on the defensive side, has not stopped. Vista's bloated and complex system has been criticized and its market share is not high. However, the ASLR mechanism introduced from vista, which is inherited from win7, has increased the threshold of attack again.

In a ROP attack, an attacker can predict the entry address of a specific function such as system or virtualprotect in advance. This is because on XP and 2000 operating systems, the dynamic link library loading addresses such as kernel32.dll are fixed, so the related function entry addresses are also fixed, that is, attackers can determine the entry addresses of these functions in advance.

Of course, one of the disadvantages of the ROP technology is to write and extract different ROP chains for different operating systems. This makes compatibility not very good.

ASLR, the full name of address space layout randomization, is a system level feature, which is first supported in Vista operating system. Its principle is that when an application or dynamic link library, such as kernel32.dll, is loaded, if it chooses to be protected by ASLR, then the system will randomly set its loaded base address. In this way, the attacker cannot predict the base address of the dynamic library, such as kernel32.dll, or determine the entry address of a specific function, such as virtualprotect.

If you are interested, you can write a simple C code to print out the loading address of VC runtime. It will be found that the loading address of VC runtime under win7 changes after each restart, but the loading address of VC runtime in XP system is fixed.

Heap Spray

The application of ASLR in the new system makes the attacker fall into a weak position in the era of buffer overflow utilization for quite a long time. But the heap spray, which was proposed long before the attacker found out (around 2001), can solve this problem. Basically, after 2005, many exploits of IE vulnerabilities used the technology of heap spray.

When the buffer overflows, we can hijack and cover an address, which makes the program crash, but only makes the program crash, which is of no value. Next, how to hand over the execution process of the program to shellcode becomes a problem. If it is overwritten to a fixed address such as 0x0c0c0c0c, 0x0a0a0a, 0x0d0d0d, it just starts from this address and is full of our shellcode. In this way, when the vulnerability is triggered, our shellcode will execute the malicious code. In practice, shellcode is preceded by some slidecode (skateboard instruction). Why add skateboard instructions instead of using shellcode to fill them all. Because if you want shellcode to execute successfully, you have to hit the first instruction of shellcode accurately. If the whole process space is shellcode, the probability of hitting shellcode accurately is greatly reduced. Because you have to hit the first instruction, plus slidecode, now as long as you hit slidecode, you can ensure that shellcode executes successfully The total length is about 50-100 bytes, while the length of slidecode is about 1 million bytes (calculated by 1m allocated to each block), so now the probability of hit is close to 99.99%. Because the slidecode is hit now, the result of executing slidecode cannot affect and interfere with shellcode. But if you just use the 0 × 90 (NOP) instruction to fill in, because the most common attack scenario now is to cover virtual function pointer (this is a multi-level pointer). In this case, if you use 0 × 90 to do slidecode and 0x0c0c0c0c to cover virtual function pointer, then the virtual table (pseudo virtual table) now is full of 0 × 90909090, and the program runs to 0 × 909090 (kernel space) )Go ahead and crash. According to this process, you can see that our slidecode also selects 0x0c0c0c. (Figure 1.2.8)

Figure 1.2.8

This is the address that will be covered after a large amount of memory is allocated


When heap spraying is carried out in the network horse, the memory size applied for is generally 200m, mainly to ensure that the address 0x0c0c0c can be covered. (Figure 1.2.9)

Figure 1.2.9

2.1 UAF Era

Because the exploitation of buffer vulnerabilities is relatively simple, the resources of these vulnerabilities are quickly exhausted in the long time of attack and defense. After 2008, the release and reuse of such vulnerability has become the mainstream of IE vulnerability. Gradually reached a peak in these years. Generally speaking, a series of operations are needed to trigger the vulnerability. A single operation, such as the creation, use and deletion of objects, is normal. The problem is a malformed combination of object operations. Because there is no standard rules for reference, the traditional methods of detecting overflow class vulnerabilities are not very suitable.

2.2 principle of object operation vulnerability

Unlike process oriented programming languages, C + + supports polymorphism and inheritance. The core of supporting these mechanisms is virtual tables. The (virtual) function pointer of C + + is located in a global array to form a virtual table. The vstr (pointer to the virtual table) is generally located in the first four bytes (32-bit system) of the object instance in memory

After that, the data members declared in the class are listed in the order of declaration. For a class with polymorphic behavior, all instances of the subclass share the same virtual table, but different from the virtual table of the parent class. For an object, when it calls a function with polymorphic behavior, it will first get the virtual table through the virtual table pointer, then get the corresponding function pointer according to the offset of the function in the virtual table, and finally call the function.

In addition, the address of the object is generally passed through registers such as ECX. Therefore, the disassembly code that calls polymorphic behavior in.C++ is similar to the following sequence. (Fig. 2.2.1)

Figure 2.2.1

Let's give a brief introduction to UAF with the demonstration code given by polynomial above stackexchange.

The following example is a piece of C + + code. (Fig. 2.2.2)

Figure 2.2.2

Can be derived as

Figure 2.2.3

Figure 2.2.4

Figure 2.2.5 shows that when account ﹣ getbalance is executed, the memory pointed to by myaccount pointer of account ﹣ destroy function is in an uncertain state. If the account "destroy" function can be triggered reliably at this time. And fill a block of carefully constructed content to the memory pointed to by myaccount pointer, the time is after the account "destroy" is executed and before the account "getbalance" is executed.

In many cases this is possible.

The account create function allocates 8 bytes of memory after execution. Balance and transactioncount take up four bytes respectively, and return a pointer to them. This pointer is stored in the myaccount variable. Account "destroy frees up this memory, but the myaccount variable still points to that 8 bytes of memory. We allocate the 8-byte content of 39 05 00 01 00 00 00 to memory reliably. Since the old 8-byte memory block has been marked for release, it is likely that the memory manager will use the newly allocated memory to cover the old memory block to the 8-byte memory that has been released. At this time, the account ﹣ getbalance function is called. It will read the 8-byte memory block, but in fact, the 8-byte memory block has been overwritten by us

Balance 39 05 00 00 (1337)

transactionCount 01 00 00 00 (1)。

So we've exceeded our authority to the next function. Of course, when it comes to ie, UAF is more complicated because of the complexity of objects.

There are DOM, BOM and JavaScript objects related to the vulnerability of object operation class in browser. Let's take the DOM object allocation process as an example.

DOM (document object model) provides an interface for manipulating HTML / XML documents. The code related to DOM implementation in IE browser is mainly in mshtml DLL. The CMarkup class in mshtml is responsible for constructing the entire HTMi tree structure, and its member function createElement calls the global createElement

Function bundles construct elements corresponding to different tags. For example, < Object > tag. Will construct the corresponding cobjectelement element: < area > tag. Will construct the corresponding careaelement element. These element classes are subclasses of the celement class. The next reverse work is mainly based on the version of IE8 8.00.7601.17537 of mshtml DLL.

For each different tag, there are different ctagdesc structures in IE explorer. One of these ctagdesc structures is the createElement function pointer to the corresponding element. Therefore, the global createElement function will get the corresponding ctagdesc structure according to different tags, and then get the pointer to the createElement function that should be tagged from it, and then call to call. See the disassembly code of the global createElement function for details, as shown in figure 2.2.6.

Figure 2.2.6

Figure 2.2.7

There are some small details here. Sometimes, when you directly use IDA to disassemble DLL files such as mshtml DLL, you can not find the corresponding symbol table. You can first download the symbol table with a small tool such as symbol type viewer and put it in the same directory as DLL, and then use IDA to disassemble the relevant DLL files.

Figure 2.2.8

Next, take cobjectelement as an example to introduce its creation process. The creation process of other elements is similar. The initialization of cobjectelement is done in the member function crcateelement function. The creation process is as follows: first allocate memory, then call constructor, and finally save the returned object pointer in the incoming CElemen** parameter. The disassembly code is shown in the figure.

Figure 2.2.9 heapalloc allocates heap memory. In some higher version of mshtml DLLs, the function processheapallocclear may allocate memory. The number of bytes passed to heapalloc is 0e0h. It can be seen that the cobjectelement size in the current IE browser version is e0h.

Next, call the constructor of cobjectetemem to initialize the cobjectelement object. The constructor will automatically call the constructor of the parent class. After calling the constructor, the new cobjcctelemenl object pointer will be saved in the passed in parameter celemen * *. This is done by the code mov ECX, [EBP + arg#8] ාmov (ECX], eax.

Ie uses reference counting bundles to track the life cycle of DOM objects. The reference counting algorithm calculates the number of pointers to each object. When there is a pointer to the object, the count value is increased by 1, and when a pointer to the acid object is deleted, the count value is decreased by L. If the count value is reduced to 0, there is no pointer to the object. At this time, the splash object can be safely destroyed. The garbage collection process is the collection of objects with a reference count of 0. The advantage of the reference counting algorithm is that the algorithm is simple to implement, and there is no need to suspend the application when garbage collection, so the recovery speed is fast. The disadvantage is that every pointer operation to an object needs to update the reference count of the object, so it will slow down the overall running speed of the system. In addition, each object that uses the reference count algorithm requires additional space to store the count value. In addition, the biggest disadvantage of the reference counting algorithm is that it cannot handle circular references. Circular references refer to two objects pointing to each other. At this time, the reference count of both objects depends on each other. Therefore, it can never be reduced to 0.

The core of IE browser's implementation of reference counting is IUnknown interface. This interface provides two very important features: lifetime control and interface query. The reference count is used to control the lifetime of an object. The caller doesn't care about the internal implementation details of the object. The pointer to the object can be obtained through the interface query. Many classes in IE browser inherit IUnknown.

IUnknown has three methods.

Figure 2.2.10 the internal implementation of the < Object > tag cobjectelement class described in the above section is an example. This class eventually inherits from celement. While celement inherits from Cbase, which implements IUnknown interface. To query the cobjectelement object corresponding to the < Object > label, the user needs to call the cobjectelement:: queryinterface function. The queryinterface function of cobjectelement will eventually call the queryinterface interface of celement. The queryinterface interface of celement will finally call the privatequeryinterface to get the object pointer.

The privatequeryinterface first calls the celement:: createtearofthunk function to return the wrapped pointer of the object, and then calls the ccaret:: AddRef function (call ECX) to increase the reference count.

The celement:: createtearofthunk function simply calls the global createtearofthunk function. The global createtearoflthunk function disassembles part of the code as shown in the figure

Figure 2.2.11 takes a look at the work done when releasing references. For celement, when the user no longer needs its reference, call celement:: release. Celement:: release is the encapsulation of celement:: privaterelease, while celemem:: privaterelease mainly calls the privaterelease function of the parent class Cbase. Cbase:: privaterelease is responsible for reducing the reference count.

In fact, there are many scenes of creating and destroying objects in ie, which is also the basis of UAF's popularity after buffer vulnerability almost disappeared in ie.

2.3 time keywords

Deferred/Delayed Free Control Flow Guard Isolated Heap

A simple example has been given above to help understand the cause and trigger of UAF. However, due to the complex calling relationship of many objects in ie, Microsoft, as a defensive party, can't exhaust and fix all potential vulnerabilities as easily as mining buffer overflow vulnerabilities. But in June and July of 2014, Microsoft introduced isolation heap and delayed release vulnerability utilization mitigation measures respectively by releasing patches. And a new mechanism control flow guard is introduced in win8.1update3 and win10. Let's briefly document these mechanisms.

The triggering and utilization of UAF depends on the reuse of released objects. The utilization process must depend on the allocation and release of illegal ie objects. The isolated heap and delayed release are protected when the objects are allocated and released.

In ie, when ctextarea:: createElement allocates memory before cve-2014-0282 patching, there is such code

Figure 2.3.1 shows the code after the vulnerability is fixed.

Figure 2.3.2 can be seen clearly that the memory allocation of the objects with UAF hidden dangers has used the isolated heap for memory allocation.

And delayed release is like this. Normal object release uses heapfree to release immediately. After adding delay release, the objects that need to be released will be uniformly recorded and then released according to the rules.

Let's talk about the mechanism of CFG (control flow guard). The mechanism of CFG is based on the assumption of control flow integrity. Here, by rewriting the binary executable file, insert a verification ID that is agreed upon when rewriting the destination address of JMP. When JMP, check whether the data in front of the destination address is the verification ID that we agreed upon. If not, enter the error processing flow.

Figure 2.3.3 introduces a CFG verification function in the call process. CFG needs the cooperation of compiler and operating system. When the verification function runs on an unsupported operating system, it returns directly. When in the supported operating system (win10 and win8.1 Update3), it will jump to a detection function in ntdll. We will not expand the detection mechanism in detail.

Because in the overflow vulnerability and most of the utilization of UAF, it depends on covering a certain address and then hijacking the EIP of the program to jump to the address of our malicious code for execution. CFG directly cut off the possibility of most exploits in controlling illegal address jump.

3.1 post UAF Era

At present, 14 years later, with the new mitigation measures, the advantages of both sides of attack and defense have almost turned to the camp of defenders led by Microsoft.

There is no fixed way to exploit the vulnerability of browser. For example, the design error of the script engine inside the browser leads to the relevant exploitation of the vulnerability by breaking through IE from the script level (cve-2014-6332). The exploitation and exploitation of the vulnerability of the flash plug-in in in the browser can obtain the RING3 permission, and then cooperate with the exploitation of the vulnerability discovered by the older font parsing engine code to obtain the system permission (relevant exploitation by hacking team). There are different ways to exploit vulnerabilities.

III. key points of IE vulnerability protection measures

July 2015 CFG compiler support.

Vs2015 RTM version introduces the / guard switch to provide compiler support for the control flow guard feature.

November 2014 CFG system level support.

Windows 8.1 update 3 provides system level support for control flow guard, and later Windows systems support this feature at the operating system level.

In July 2014, ms14-037 patch was released to introduce the delayed free feature.

In June 2014, ms14-035 patch was released to introduce the isolated head feature.

January 2008 sehop system level support

Release the vista Service Pack 1 patch package and introduce the operating system support for the SEOP feature. Windows systems since Vista SP1 support this feature at the operating system level.

ASLR system level support January 2007

Windows Vista system introduces support for ASLR feature operating system level. Windows systems since Vista support this feature at the operating system level.

Safeseh / stack Cookie / ASLR / dep compiler support in early 2006

VS2005 introduces / safeeh compilation switch to mitigate the overflow vulnerability, and / GS compilation switch to insert stack cookie to mitigate the attack on return address, and / dynmicbase compilation switch to add

Compiler support for ASLR feature is introduced, and compiler support for dep feature is introduced with / nxcompat compile switch. Compilers since VS2005 support the above compilation switches.

Dep system level support August 2004.

Microsoft introduced XP Service Pack 2 patch package to support the operating system of DEP feature. Since XP SP2, windows system supports this feature at the operating system level.