Trend Micro Facebook TrendLabs Twitter Malware Blog RSS Feed You Tube - Trend Micro
Search our blog:

  • Recent Posts

  • Calendar

    May 2015
    S M T W T F S
    « Apr    
  • Email Subscription

  • About Us

    Author Archive - Jack Tang (Threats Analyst)

    Our analysis of the win32k.sys vulnerability used in a recent targeted attack reveals that it opens up an easy way to bypass the sandbox, making it a bigger threat than originally thought.

    As mentioned in Microsoft security bulletin MS15-051, CVE-2015-1701 is an elevation of privilege vulnerability that exists when the Win32k.sys kernel-mode driver improperly handles objects in memory. The vulnerability exists in Win32k.sys, which is a weak security point in Windows.

    Elevation of privilege vulnerabilities are technically less dangerous since they can’t be exploited remotely, but since this vulnerability can be used to bypass the sandbox — a security feature designed to keep attackers from being able to execute malicious files in users’ environment — this becomes a viable tool for attackers.

    The vulnerability exists in the Windows OS process of creating windows for applications. To illustrate, we’ll first look at the processes involved when an application wants to create a window:

    1. The application registers a window class to System, which defines the window’s style and behavior. The most important property of window class is window procedure which defines the window ‘s behavior when there’s an incoming message. The window procedure is provided by the application.
    2. The application then calls the API CreateWindow/CreateWindowEx with the window class to create the window. These APIs will switch to kernel mode to call service routine NtUserCreateWindowEx. NtUserCreateWindowEx is complicated function and does the real job of creating the window in Windows system.  During the function execution, it will switch to user mode many times to call many functions that exist in user mode. These function do jobs which is fit to run in the user mode (example: to load an image, etc.).

    Since this is a lengthy process, I’ve simplified the process of creating a window, leaving only the key point related to the vulnerability: Read the rest of this entry »

    Posted in Exploits, Vulnerabilities |

    One of the vulnerabilities recently patched by Microsoft can be exploited in the same way as Heartbleed, and needs to be addressed immediately.

    Addressed in the April batch of Patch Tuesday fixes (in Microsoft Security Bulletin MS15-034, specifically), the Microsoft Windows HTTP.sys Integer Overflow vulnerability, or CVE-2015-1635, is a remote code execution vulnerability that exists in HTTP.sys, or the HTTP protocol processing module in Microsoft Internet Information Service. Integer overflows have long been known as one kind of notorious and fairly old vulnerability – so why the sudden interest? I found that the vulnerability can be easily used for denial of service (DoS) attacks or data leaks similar to last year’s Heartbleed attack, in which information is copied from memory and sent to the client.

    A researcher already published a checker script for this vulnerability on Pastebin and showed how it can be used to carry out DoS attacks or to leak information. Additionally, another researcher published a POC for information leaks.

    Detailed analysis of DoS attacks and Information leak attacks via CVE-2015-1635

    In this blog post I will explain in detail how the vulnerability can be used for DoS attacks and data leak attacks. Before I dive into the vulnerability, let’s introduce some background information.

    Figure 1. Architecture of IIS

    After installing IIS (Internet Information Service) on the system, there is a service named the World Wide Web Publishing Service, which I call the WWW service. When a client sends an HTTP request to the system, the WWW service starts up or selects a worker process (W3wp.exe) based on load balancing policy to process the HTTP request and send the appropriate HTTP response. The file W3wp.exe uses HTTP.sys to do many tasks related to HTTP protocol handling, which include HTTP protocol parsing, response content assembling, and content caching. HTTP.sys receives the HTTP request and sends the HTTP response via TCPIP.sys.

    How can this be used in DoS attacks?

    Let’s prepare a HTTP request to start our DoS journey. The testing environment I used was Windows 8.1 (32-bit version) plus IIS 8.5.

    First, we take the IIS ‘s default web page iisstart.htm (file size 694 bytes) as an example. We compose a HTTP request as follows:

    GET /iisstart.htm HTTP/1.1\r\nHost: aaaaa\r\nRange: bytes=284-18446744073709551615 \r\n\r\n

    The HTTP range request start position is 284, and the end position is 18446744073709551615. The hexadecimal value of 18446744073709551615 is 0xFFFFFFFFFFFFFFFF. The range length is huge—it must be over the size of the requested web page file, which appears suspicious. I will explain later why I selected the start position as 284.

    After the request is sent to HTTP Server, one w3wp.exe handles the HTTP request processing. TCPIP.sys forwards any HTTP protocol content to HTTP.sys. If the request is a HTTP range request, it will call the function UlpParseRange(). The function parses the request to get the requested range’s start position and end position and calculates the range’s length. We can see that the first integer overflow happens in code which calculates the range’s length. The code is as follows:

    Figure 2. Range Length code

    When the end position=0xFFFFFFFFFFFFFFFF and start position=0, the integer overflow happens and the Range Length equals 0. The code does not check whether there is an overflow and does not take the error handling action.

    In our case, the integer overflow does not happen. The end position=0xFFFFFFFFFFFFFFFF and start position=284, while Range Length equals -284, whose hexadecimal value is 0xFFFFFFFFFFFFFEE4. If this is interpreted as an unsigned integer, the value is very huge.

    After finishing parsing the HTTP request, it will call the function UlAdjustRangesToContentSize(). The function adjusts the Range’s start position and length if the start position and length is “invalid”. The definition of “invalid” contains several scenarios which indicate the Range is over the requested web page content. Examples include:

    • Range Start Position is 0xFFFFFFFFFFFFFFFF
    • Range Length is 0xFFFFFFFFFFFFFFFF
    • Start Position >= the requested web page length
    • End Position >= the requested web page length

    The second integer overflow can be found in the last function. It uses the following code to get the Range End Position:

    Figure 3. Adjustment action

    In this case, the Range Start Position equals 284, Range Length equals 0xFFFFFFFFFFFFFEE4, so an overflow happens, Range End Position equals 0 and the adjusted action is bypass.

    If one same request is received continuously, the request‘s response will be cached and will be taken from the cache and sent to the requester. It will call the function UxpTpDirectTransmit().One job of the function is to calculate the HTTP response packet length. The simplified code is as follows:

    Figure 4. Simplified HTTP code

    Using our case‘s value:

    Range Count = 1;
    Range Boundary and Range Info length = 0; // (This will be explained later.)
    Range Tail Boundary Length = 0; // (This will be explained later.)
    Range Length = 0xFFFFFEE4; // (The value is already cast to 32 bit)
    HTTP Head Length = 283;

    The HTTP Response Length‘s result is 0xFFFFFFFF. The whole length is 4G. Systems will consider that this HTTP response total size is 4G. This means that there is a HTTP response packet whose calculated size is larger than the real size. This is why we used 284 as the Range Start Position.

    HTTP Response Length = HTTP Head Length + (Range End Position – Range Start Position + 1)
    = HTTP Head Length + (0xFFFFFFFF – Range Start Position + 1
    = HTTP Head Length - Range Start Position

    If Range Start Position less than <= HTTP Head Length, it will trigger an overflow. The HTTP Response Length value range is [0, HTTP Head Length).

    Because we want to launch a DoS attack, this is not the result we want. We want the HTTP Content Length value to be large. The preferred range for Range Start Position is [HTTP Head Length+1, target page size). In this range, it does NOT trigger an overflow and the HTTP Content Length value will become large, and will then allow a DoS attack.

    After the HTTP response package is assembled, HTTP.sys will forward the packet information to the protocol stack driver to send it. TCPIP.sys‘s function TcpSegmentTcbSend() will traverse every part content of the packet. There is integer overflow in the function. Here is a list of some simplified code:

    Figure 5. Simplified code

    In the above code, line 15 will trigger the overflow. In our case, the HTTP Response Length is 0xFFFFFFFF. The “virtual address’” initial value must be a kernel address ( >=0x80000000). Because HTTP Response Length is very large, the loop will run many times. When the loop has run many times, the “virtual address” will become a very small value after triggering the integer overflow. In the loop, it will use the “virtual address” to build a partial memory descriptor list (MDL). Because the range is not a sub range in the source range, it leads to a Blue Screen Of Death (or BSOD). The DoS attack is complete.

    How can this be used in an information theft attack?

    We prepare a request as follows:

    GET /iisstart.htm HTTP/1.1\r\nHost: aaaaa\r\nRange: bytes=3-18446744073709551615, 1-600"+ "\r\n\r\n"

    The reason for using multiple ranges will be explained later. We take 3-18446744073709551615 as Range1 and take 1-600 as Range2.

    In function UlpParseRange(),the code can be seen in Figure 3. For this case, we have 2 range lengths:

    Range1 Length = 0xFFFFFFFFFFFFFFFF - 0x3 + 1 = 0xFFFFFFFFFFFFFFFD
    Range2 Length = 600 -1 + 1 = 600

    After parsing the HTTP request, it will call the function UlAdjustRangesToContentSize(). The code is in Figure 3. Range1 will trigger integer overflow (3 + 0xFFFFFFFFFFFFFFFD => 0), so bypass adjust action, even if the Range1 Length is invalid. Range2 is valid, so it should not be adjusted.

    If the same request is received continuously, the request‘s response will be cached and will be taken from the cache and sent to the requester. It will call the function UxpTpDirectTransmit() . The code in Figure 4 is executed, using the following values:

    • Range Count = 2
    • Range1 Length = 0xFFFFFFFFFFFFFFFD
    • Range2 Length = 600
    • Http Head Length= 0x127 //HTTP head content, see Figure 6
    • Range1 Boundary and Range1 Info length = 0x7a
    • Range2 Boundary and Range2 Info length = 0x69
    • Range Tail Boundary Length = 0x32; //see Figure 8

    By using a multi-range request, there is a Range bound tag and Range Information (Content-Type, Content-Range) before each range content. (See Figure 7 for this.)

    Figure 6. HTTP Head

    Figure 7. Range boundary tag and Range Information

    Figure 8. Range Tail

    From Figure 4, we can see that HTTP Response Length = HTTP Head Length + Range Boundary and Range Info length + Range1 Length + Range Boundary and Range Info length + Range2 Length = 0x127+7a+0xFFFFFFFD+0x69+0x258+0x32 => 0x491. At line 5 of Figure 4, an integer overflow occurs when 0xFFFFFFFD is added. At this time, the system takes 0x491 as the HTTP response length.

    The memory status can be described as following:

    Figure 9. Memory status

    After assembling the HTTP response package, HTTP.sys will forward the packet information under the protocol stack driver to send it. TCPIP.sys ‘s function TcpSegmentTcbSend() will traverse every part content of the packet (see Figure)

    See the code in Figure 4. In this case, the HTTP response length is 0x491. When handling the part which length is 0xFFFFFFFD, line 7’s condition is met, Part Length‘s value will be set by Remain Length. At that point, Remain Length is 0x2f0 (0x491 – 0x172- 0x7a). It will use [0x3, 0x3+0x2f0] as a buffer range to read and send to client. Our target web page iistart.html has a length 0x2b6. The status is the following:

    Figure 10. Buffer status

    In Figure 10, the red part is the leaked information buffer. Compared with the code in Figure 5, the condition at line 24 is satisfied and breaks the loop. That is to say, the parts after the part which has 0xFFFFFFFD length will not be sent to client. At this point, we can see why we used a multi-range request.

    Using multi-range requests can let the HTTP response length (calculated in step 3) become larger to leak more information. If only a single range is used, the HTTP response length becomes either too big or too small. If the HTTP response length is too big, it will lead to BSOD, as it was described in the previous section. If the HTTP response length is small, it doesn’t make a range to cover the buffer after the target web page content to do information leak. Attackers use many range to leak more information. For example, I created a multi-range request as follows:

    GET /iisstart.htm HTTP/1.1\r\nHost: aaaaa\r\nRange: bytes=3- 18446744073709551615,1-32,32-64, 64-96,96-128,128-256, 129-130,130-140,160-170,180-190, 190-200"+ "\r\n\r\n"

    In the request, I use 11 ranges. The leaked information can be seen in the following picture:

    Figure 11. Information leakage


    Given these attack scenarios, I strongly advise users and network administrators to apply the patch, if they haven’t. Aside from the update provided by Microsoft, Deep Security also protects users from this through the following Deep Security rule:

    • 1006620 – Microsoft Windows HTTP.sys Remote Code Execution Vulnerability (CVE-2015-1635)

    This blog post is a follow-up to our previous blog entry on CVE-2015-1635:
    IIS At Risk: The HTTP Protocol Stack Vulnerability

    Posted in Exploits, Vulnerabilities |

    As operating system developers are always keen on improving exploit mitigation technology, Microsoft has enabled a new mechanism in Windows 10 and in Windows 8.1 Update 3 (released last November) by fault. This technology is called Control Flow Guard (CFG).

    Previous mitigation techniques like address space layout randomization (ASLR) and Data Execution Prevention (DEP) have been successful in making exploitation of vulnerabilities more difficult, even if these techniques are not perfect. ASLR causes the development of heap sprays, and DEP results in return-oriented-programming (ROP) techniques showing up in the exploit code.

    To explore this particular technology, I used the Windows 10 Technical Preview (build 6.4.9841),  with test applications built using the Visual Studio 2015 Preview. Because the CFG implementation of the latest Windows 10 technical preview build (10.0.9926) has a slight change at that same point, I will point out the difference.

    To fully implement CFG, both the compiler and the operating system must support it properly. As an exploit mitigation mechanism in the system level, the CFG implementation requires cooperation from the compiler, the operating system user mode library, and the kernel mode module. A blog post on MSDN outlined the steps that developers need to do to support CFG.

    Microsoft’s implementation of CFG is focused on indirect call protection. Consider the following code in the test program I created:

    Figure 1. Code of test application

    Let’s take a look at what the encircled code compiles into if CFG is not enabled.

    Figure 2. Assembly code of test program

    In the above figure, there is one type of indirect call. Its target address is not decided at compilation and is instead decided at runtime. An exploit can abuse this as follows:

    Figure 3. How to abuse the indirect call

    Microsoft’s implementation of CFG focuses on mitigating problems if the indirect call is exploited and an invalid target is called (in an exploit, this would be to first stage shellcode).

    The invalid target has a distinguishing characteristic: in most cases it is not a valid function starting address. Microsoft’s CFG implementation is based on the idea that an indirect call’s target must be the start of a valid function. What is the resulting assembly code if CFG is enabled?

    Figure 4. Assembly code, with CFG enabled

    Before the indirect call, the target address is passed to the _guard_check_icall function, which is where CFG is actually implemented. In versions of Windows without CFG support, this function does nothing. In Windows 10, which does have CFG support, it points to ntdll!LdrpValidateUserCallTarget. This function takes a target address as argument and does the following:

    1. Access a bitmap (called CFGBitmap) which represents the starting location of all the functions in the process space. The status of every 8 bytes in the process space corresponds to a bit in CFGBitmap. If there is a function starting address in each group of 8 bytes, the corresponding bit in CFGBitmap is set to 1; otherwise it is set to 0. The figure below is an example of a portion of CFGBitmap:

      Figure 5. Representation of CFGBitmap

    2. Convert the target address to one bit in CFGBitmap. Let’s take 00b01030 as example:

      Figure 6. Target address

      The highest 3 bytes (the 24 bits encircled in blue) is the offset for CFGBitmap (unit is 4 bytes/32 bits). In this example, the highest three bytes are equal to to 0xb010. Therefore, the pointer to a four byte unit in CFGBitmap is the base address of CFGBitmap plus 0xb010.

      Meanwhile, the fourth bit to the eighth bit is (the five bits encircled in red) have the value X. If target address is aligned with 0x10 (target address & 0xf == 0), then X is the bit offset value within the unit. If the target address is not aligned with 0x10 (target address & 0xf != 0), the X | 0x1 is the bit offset value.

      In this example, the target address is 0x00b01030. X has the value of six. The formula 0x00b01030 & 0xf has a result of zero; this means the bit offset is also six.

    3. We look at the bit identified in step #2. If the bit is equal to 1, it means the indirect call target is valid because it is a function’s starting address. If the bit is 0, it means the indirect call target is invalid because it is not one function’s starting address. If the indirect call target is valid, the function will do nothing and let it go. If the indirect call target is invalid, an exception will be raised which should prevent further exploit code from running.

      Figure 7. Value in CFGBitmap

    The implementation of CFG should be useful in preventing some classes of exploits. This will help reduce the threat from software vulnerabilities in the long run.

    You may read a detailed analysis about Control Flow Guard in our technical report, Exploring Control Flow Guard in Windows 10.

    Posted in Vulnerabilities | Comments Off on Exploring Control Flow Guard in Windows 10

    Applications that have been frequently targeted by exploits frequently add sandboxes to their features in order to harden their defenses against these attacks. To carry out a successful exploit, an attacker will have to breach these sandboxes to run malicious code. As a result, researchers will pay particular attention to exploits that are able to escape sandboxes.

    In both October and November Patch Tuesday cycles, Microsoft addressed several vulnerabilities that were used by attackers to escape the Internet Explorer sandbox. One of these was CVE-2014-6349, which was addressed by Microsoft as part of MS14-065, November’s cumulative Internet Explorer patch. We chose this particular vulnerability for two reasons: exploiting it is relatively easy, and its methodology – using shared memory to escape the Internet Explorer sandbox – has not been seen before. A separate vulnerability that also allowed for sandbox escapes – CVE-2014-6350 – was also fixed in the same patch, and Google released details about this second vulnerability earlier this week.

    Internet Explorer 11 exposes a shared memory section object to all tab process (which are sandboxed). This is used to store various Internet Explorer settings. Normally, the tab processes only read this to see these settings. However, in Enhanced Protected Mode (EPM, which is IE’s sandbox mode), the shared memory section‘s DACL (Discretionary Access Control List) is not configured correctly. The tab processes have “write” permission to modify the shared memory section content. This can be used by an attacker to break the IE sandbox. How can this be done? We will explain this in the rest of this post.

    To understand the concepts covered in this post, background knowledge about Protected Mode (PM) and EPM is necessary. These MSDN documents and HITB presentations provide background information on these topics. I carried out my tests on a system running Windows 8.1 with Internet Explorer 11.0.9600.17107.

    After enable IE 11’s EPM mode,  we run IE. The broker process and tab process are seen below:

    Figure 1. Internet Explorer broker and tab processes

    The parent iexplore.exe broker process’s integrity is Medium. The iexplore.exe tab process’s integrity is AppContainer. This means the web page rendering in the sandboxed tab process is in the sandbox and its privilege is controlled. Both process share a memory section: \Sessions\1\BaseNamedObjects\ie_ias_<frame process id>-0000-0000-0000-000000000000.

    Read the rest of this entry »

    Posted in Exploits, Vulnerabilities | Comments Off on Escaping the Internet Explorer Sandbox: Analyzing CVE-2014-6349

    We see many kinds of vulnerabilities on a regular basis. These range from user-after-free (UAF) vulnerabilities, to type confusion, to buffer overflows, to cross-site scripting (XSS) attacks. It’s rather interesting to understand the root cause of each of these vulnerability types, so we looked at the root cause of an Internet Explorer vulnerability – CVE-2014-1772.

    We’d privately disclosed this vulnerability to Microsoft earlier in the year, and it had been fixed as part of the June Patch Tuesday update, as part of MS14-035. While this vulnerability was already patched some time ago, it is still a good example of UAF vulnerabilities in general.

    The code to trigger this vulnerability is below:

    Figure 1. HTML code to trigger vulnerability

    Before debugging, several flags must be set to make the job of analysis easier. Run the command gflags.exe /i iexplore.exe +hpa +ust to to enable the page heap (HPA) and user stack trace (UST) flags. This will make finding memory corruption and tracing heap allocation and frees easier. This file can be found in the Windbg installation folder. You can now run windbg, attach Internet Explorer, and use it to access the HTML file.

    Examining the JavaScript execution flow, when line 18 of the HTML code is executed, the crash happens:

    Figure 2. Output of crash

    We can see the EDI register point to a freed memory space, which leads to an access violation.

    What is the value of the EDI register? Let us look at the code below.

    Figure 3. Assembly code

    The above code tells us that the EDI is from the first argument, which is the CTreePos* type. We can assume the EDI is a pointer of CTreePos. Since the CTreePos object is freed, how can we get where the object is freed? Because the UST flag is set, we can use the !heap -p -a edi command in windbg.

    Figure 4. Call stack

    The above figure shows us the call stack of the CTreePos object freed. The call stack has a lot of information. We see the function CMarkup::FreeTreePos; this evidence gives us evidence that the freed object is CTreePos object and that this is a use-after-free issue.

    Since it is a UAF issue, we want to deeply understand the issue. We need to locate where the CTreePos object is created, where the object is freed, and where the freed object is used again. Figure 4 gives us where the object was freed. To find where is used again, we need to examine the crash point. The call stack is as follows:

    Figure 5. Call stack

    How do we find the location where the CTreePos object was created? There are many ways. I prefer to run the sample again, and break the object freed point and use the !heap -p -a xxxx command to trace back to where the object is created. The call stack is as follows:

    Figure 6. Call stack

    For UAF problems, I prefer to compare the 3 locations (create, free, use again) to find some clues.

    Figure 7. Call stacks

    There are 3 columns in Figure 7. They are call stack trace summaries: from left to right, it is when the object is created, freed, and used again. In the above example, the direction of the stack is from the bottom to the top.

    There is plenty of useful information here. First, we can find the relationship between the 3 parts. Under the yellow line, CDoc::CutCopyMove is the last identical function in the creation call stack trace and the free call stack trace. This means the execution flow creates the CTreePos object and then frees the object in CDoc::CutCopyMove. Under the red line, the execution flow frees the object and then uses it again (and crashes) in CSpliceTreeEngine::InsertSplice.

    In the second column, we find the execution flow in the CSpliceTreeEngine::InsertSplice function encounters a failure and call the Fire_onerror function. The function will call the JavaScript object’s onerror event. At the event, the execution will call CMarkupPointer::UnEmbed to free the object.

    Right away, we have four questions.

    1. Why does it trigger an onerror event?
    2. Why does it create the CTreePos object?
    3. Why does it free the CTreePos object?
    4. Why does it use the freed object again?

    Before answering these questions, I want to summarize some background knowledge about how Internet Explorer’s DOM tree implementation. Because IE is not open source, this information is gathered by reverse engineering, so it may not be 100% accurate.

    One page has a CMarkup object to represent the page’s skeleton or DOM tree. The CMarkup object contain a pointer to the root CElement object. This is the parent class of many concrete element classes. In Figure 1, the Javascript object e_1 and e_2 are the CObjectElement objects which are inherited from CElement. The CElement object has a pointer to a CTreeNode object. The CTreeNode object also has a pointer to a related CElement object. The CTreeNode’s object has a pair of pointer to CTreePos objects.

    Why is a CTreePos object needed? This is because IE uses a Splay Tree algorithm to manuiplate the DOM tree. In the Splay Tree, the CTreePos object is the node that is involved in the algorithm. The CMarkupPointer object represents a location in the CMarkup object (DOM tree). So the CMarkupPointer object has a pointer to CTreePos to represent its location. CMarkupPointer has several statuses which are related to UAF issues.

    • Embed status: this means CMarkupPointer created CTreePos, which is added to the Splay Tree.
    • Unembed status: this means CMarkupPointer removes the CTreePos from the Splay Tree and frees it.

    The following graph describes the interactions involving the splay tree.

    Figure 8. Splay tree graph

    Going back to our four questions, we can now attempt to answer them.

    Why does it trigger an onerror event?

    From Figure 1’s Javascript code, we can see e_2.onerror sets a handler function. At line 22, e_2.swapNode will trigger DOM tree’s changing; this calls the CObjectElement::CreateObject function. This function checks the object’s CLSID. Because e_2’s CLSID is not set, it triggers the onerror event handler.

    In the handler, at line 22, the Javascipt code r.insertNode(e_2) will change the DOM tree once again and change CObjectElement::CreateObject as well; because e_2 has no CLSID , it will again trigger the onerror event handler once again. The second time the this handler runs, at r.setEnd(document.all[1],0)” , it frees the CTreePos object.

    Why does it create the CTreePos object?

    From Figure 6, the CTreePos object is created in calling the CDomRange::InsertNode function. We can map this function to Figure 1’s line 19: r.insertNode(e_2). The CDomRange::InserNode function will insert elements into the DOM tree. The function is called Doc::CutCopyMove to modify the DOM tree and takes several arguments. The first CMarkupPointer type argument is the source start location in CMarkup (DOM tree) . The second CMarkupPointer type argument is the source end location in CMarkup (DOM Tree). The third CMarkupPointer type argument is the target location in CMarkup (DOM Tree).

    Doc::CutCopyMove will copy or move the source sub DOM tree to the target location in DOM tree. Because of the use of the Splay Tree algorithm (which uses CTreePos as a node), the function needs to create a CTreePos object and add it to the SplayTree for source CMarkup (DOM tree) and target CMarkup (DOM Tree). Doc::CutCopyMove calls CMarkup::DoEmbedPointers to let the CMarkupPointer change to embed status. Finally, the CTreePos object is created. The UAF CTreePos object is created for the e_1 JavaScript element.

    Why does it free the CTreePos object?

    From the call stack trace when the CTreePos object is freed (Figure 4), we can find CDomRange::setEnd. This function can be mapped to line 17 in Figure 1: r.setEnd(e_1,0). That means the CTreePos object is in the implementation of setEnd. The CDomRange::setEnd function wants to replace the original end point with a new end point. This function finally calls CMarkupPointer::MoveToPointer to move to the specific DOM tree location. It will first call CMarkupPointer::UnEmbed to change this CMarkupPointer object to unembed and remove CTreePos from the Splay Tree and free it. The JavaScript code r.setEnd‘s argument is the e_1 element. So the CTreePos object related with the e_1 element is freed.

    Why does it use the freed object again?

    In Figure 7, under the red line is the function call for CSpliceTreeEngine::InsertSplice. Column B is CSpliceTreeEngine::InsertSplice+0x13ff. Column C is CSpliceTreeEngine::InsertSplice+0x6EDD4A. Column B is the free call stack trace and Column C is the “used again” crash call stack trace. This means that both “free” and “used again” happen in one function called CSpliceTreeEngine::InsertSplice. We trace the execution flow in this function, and find the following:

    Figure 9. Assembly code

    Instruction 636898C4, eax is the address of the UAF CTreePos Objects. The function saves the address to a local variable var_1E4. Then, it proceeds to 6368AA9A.

    Figure 10. Assembly code

    At 6368AA9A, it calls a virtual function CObjectElement::Notify. We can find here the call stack trace from Figure 7’s column B. This means when running this call, it encounters an error and calls the onerror event handler . That frees the CTreePos object. However, the CSpliceTreeEngine::InsertSplice function local variable var_1E4 holds a reference to this freed object. It then proceeds to 63D7735B.

    At 63D7735B , it calls CElment::RecordTextChange ForTsf with var_1E4 as the second argument. When this function is run, if any instruction accesses the contents of the CTreePos object, a crash occurs.


    In brief, the UAF issue’s root cause is that under the event interaction context, CSpliceTreeEngine::InsertSplice doesn’t handle local variable reference validation properly.

    DOM is based on event mechanisms. Under complex event interaction contexts, it is a significant challenge to solve UAF issue completely. However, in recent patches Microsoft has introduced memory protection in Internet Explorer, which helps mitigate UAF issues (especially in cases where a UAF object is referenced from the call stack).

    This highlights one important reason to upgrade to latest versions of software as much as possible: frequently, new techniques that make exploits more difficult are part of newer versions, making the overall security picture better.

    Trend Micro Deep Security protects users against this particular threat. The following rule, released as part of the regular updates released in June is applicable:

    • 1006036 – Microsoft Internet Explorer Memory Corruption Vulnerability (CVE-2014-1772)
    Posted in Exploits, Vulnerabilities | Comments Off on Root Cause Analysis of CVE-2014-1772 – An Internet Explorer Use After Free Vulnerability


    © Copyright 2013 Trend Micro Inc. All rights reserved. Legal Notice