IE Scripting Flaw Still a Threat to Unpatched Systems: Analyzing CVE-2018-8653

Microsoft recently patched a critical flaw in Internet Explorer’s scripting engine that could lead to remote code execution. The vulnerability is being exploited in the wild and was originally reported by a researcher from Google’s Threat Analysis Group. Microsoft released an out-of-band patch to fix the vulnerability before the normal patch cycle. McAfee products received […]

The post IE Scripting Flaw Still a Threat to Unpatched Systems: Analyzing CVE-2018-8653 appeared first on McAfee Blogs.

Microsoft recently patched a critical flaw in Internet Explorer’s scripting engine that could lead to remote code execution. The vulnerability is being exploited in the wild and was originally reported by a researcher from Google’s Threat Analysis Group. Microsoft released an out-of-band patch to fix the vulnerability before the normal patch cycle. McAfee products received an update to detect the threat shortly after the patch was released.

A remote attacker can target Internet Explorer Versions 9 through 11 via a specially crafted website, while a local attacker on a rogue network could also target the Web Proxy Auto-Discovery service, which uses the same vulnerable scripting engine (jscript.dll). Microsoft Edge is not affected; however, other Windows applications that include the scripting engine might be vulnerable until the security patch from Microsoft is applied.

Context

Vulnerabilities targeting Internet Explorer that can be triggered either remotely or locally are prime tools for cybercriminals to compromise many unpatched computers. That is why criminals usually integrate those vulnerabilities into exploit kits, which propagate malware or conduct other nefarious activities against compromised hosts. The threat of exploit kits is one reason to track this type of vulnerability and to ensure all security patches are deployed in a timely manner. In 2018, more than 100 memory corruption vulnerabilities were found in a Microsoft scripting engine (either for Internet Explorer or Edge). See the MITRE website for more details. (For defense-in-depth, products such as McAfee Endpoint Security or McAfee Host Intrusion Prevention can detect and eradicate such threats until patches can be applied.)

Once a CVE ID is released, cybercriminals can take as little as a few weeks (or in some cases days) to integrate it into their exploit kit. For example, CVE-2018-8174 was initially reported to Microsoft in late April by two teams of threat researchers who had observed its exploitation in the wild. Microsoft published an advisory within a week, in early May. Meanwhile, the researchers published their security analysis of the exploit. Only two weeks later a proof-of-concept exploit was publicly released. In the next couple of weeks exploit kits RIG and Magnitude integrated their weaponized versions of the exploit. (A more detailed timeline can be found here.)

It took less than a month for cybercriminals to weaponize the vulnerability initially disclosed by Microsoft; therefore, it is critical to understand the threat posed by these attack vectors, and to ensure counter measures are in place to stop the threat before it can do any damage.

Technical details

The IE scripting engine jscript.dll is a code base that has been heavily audited:

It is no surprise that exploitable bugs are becoming more exotic. This is the case for CVE 2018-8653, which takes three seemingly innocent behaviors and turns them into a use-after-free flaw. A Microsoft-specific extension triggers a rarely explored code path that eventually misbehaves and invokes a frequently used function with unusual arguments. This leads to the use-after-free condition that was exploited in the wild.

The enumerator object: The entry point for this vulnerability is a Microsoft-specific extension, the enumerator object. It offers an API to enumerate opaque objects that belong to the Windows world (mostly ActiveX components, such as a file system descriptor used to list drives on a system). However, it can also be called on a JavaScript array. In this situation, one can access the array member as usual, but objects created this way are stored slightly differently in memory. This is the cause of interesting side effects.

The objects created by calling the Enumerator.prototype.item() function are recognized as an ActiveXObject and, as seen in the creation of eObj, we can under certain circumstances overwrite the “prototype” member that should have been a read-only property.

Unexpected side effect: The ability to overwrite the prototype member of an ActiveXObject can seem innocuous at first, but it can be leveraged to explore a code path that should not be reachable.

When using the “instanceof” keyword, we can see that the right side of the keyword expects a function. However, with a specially crafted object, the instanceof call succeeds and, worse, we can control the code being executed.

The edge case of invoking instanceof on a specially crafted ActiveXObject gives us the opportunity to run custom JavaScript code from a callback we control, which is typically an error-prone situation.

Attackers successfully turned this bug into a use-after-free condition, as we shall see next.

Exploiting the bug: Without getting into too much detail (see the proof of concept later in this document for more info), this bug can be turned into a “delete this” type of primitive, which resembles previously reported bugs.
When the callback function (“f” in our previous example) is invoked, the keyword “this” points to eObj.prototype. If we set it to null and then trigger a garbage collection, the memory backing the object can be freed and later reclaimed. However, as mentioned in the Project Zero bug report, to be successful an entire block of variables needs to be cleared before the memory is freed.

The out-of-band patch: Microsoft released an unscheduled patch to fix this vulnerability. It is common practice for us to look at what changed before and after the patch. Interestingly, this patch changes the strict minimum number of bytes, while the version number of the DLL remains unchanged.

Using the popular diffing tool Diaphora, we compared the version of jscript.dll for Windows 10, x64-bit edition (feature version 1809).

We can see that only a few functions were modified. All but one point to array-related functions. Those were probably patches addressing CVE 2018-8631 (jscript!JsArrayFunctionHeapSort out-of-bounds write). The only one remaining that was substantially modified is NameTbl::InvokeInternal.

Diaphora provides us with a diff of the assembly code of the two versions of the function. In this instance, it is easier to compare the functions side by side in Ida Pro to see what has changed. A quick glance toward the end of the function shows the introduction of two calls to GCRoot::~GCRoot (the destructor of the object GCRoot).

Looking at the implementation of ~GCRoot, we see it is the same code as that inlined in that function created by the compiler in the older version of the DLL.

In the newer version of the DLL, this function is called twice; while in the unpatched version, the code was called only once (inlined by the compiler, hence the absence of a function call). In C++ parlance, ~GCRoot is the destructor of GCRoot, so we may want to find the constructor of GCRoot. An easy trick is to notice the magic offset 0x3D0 to see if this value is used anywhere else. We find it near the top of the same function (the unpatched version is on the left):

Diving into the nitty gritty of garbage collection for jscript.dll is beyond the scope of this post, so let’s make some assumptions. In C++/C#, GCRoot would usually design a template to keep track of references pointing to the object being used, so those do not have garbage collection. Here it looks as though we are saving stack addresses (aka local variables) into a list of GCRoot objects to tell the garbage collector not to collect the objects whose pointers are on those specific locations on the stack. In hindsight this makes sense; we were able to “delete this” because “this” was not tracked by the garbage collector, so now Microsoft makes sure to specifically add that stack variable to the tracked elements.

We can verify this hypothesis by tracing the code around an invocation of instanceof. It turns out that just before invoking our custom “isPrototypeOf” callback function, a call to NameTbl::GetVarThis stores a pointer in the newly “protected” stack variable and then invokes ScrFncObj::Call to execute our callback.

Looking at unexpected behavior in `instanceof`: Curious readers might wonder why it is possible to invoke instanceof on a custom object rather than on a function (as described previously). When instanceof is invoked in JavaScript, the CScriptRuntime::InstOf function is called behind the scene. Early on, the function distinguishes two cases. If the variable type is 0x81 (which seems to be a broad type for a JavaScript object on the heap), then it invokes a virtual function that returns true/false if the object can be called. On the other hand, if the type is not 0x81, a different path is followed; it tries to automatically resolve the prototype object and invoke isPrototypeOf.

The 0x81 path:

The not 0x81 path:

 

 

Proof of concept

Now that we have seen the ins and outs of the bug, let’s look at a simple proof of concept that exhibits the use-after-free behavior.

First, we set up a couple of arrays, so that everything that can be preallocated is allocated, and the heap is in a somewhat ready state for the use after free.

Then, we declare our custom callback and trigger the vulnerability:

For some reason, the objects array needs to be freed and garbage collected before the next step of the exploit. This could be due to some side effect of freeing the ActiveXObject. The memory is reclaimed when we assign “1” to the property reallocPropertyName. That variable is a magic string that will be copied over the recently freed memory to mimic legitimate variables. It is created as shown:

The 0x0003 is a variable type that tells us the following value is an integer and that 1337 is its value. The string needs to be long enough to trigger an allocation of the same or similar size as the memory block that was recently freed.

To summarize, JavaScript variables (here, the RegExp objects) are stored in a block; when all the variables from the block are freed, the block itself is freed. In the right circumstances, the newly allocated string can take the place of the recently freed block, and because “this” is still dangling in our callback, it can be used for some type confusion. (This is the method used by the attackers, but beyond the scope of this post.) In this example, the code will print 1337 instead of an empty RegExp.

McAfee coverage

Please refer to the McAfee product bulletin for full coverage updates. Here is a short summary of current product coverage as of this writing.

Endpoint products: Endpoint Security (ENS), ENS Adaptive Threat Protection (ENS-ATP), Host Intrusion Prevention (HIPS), VirusScan Enterprise (VSE), WSS.

  • ENS (10.2.0+) with Exploit Prevention
    • Proactively covered by McAfee Generic Buffer Overflow Protection Signature ID 428
  • HIPS (8.0.0+)
    • Proactively covered by McAfee Generic Buffer Overflow Protection Signature ID 428
  • ENS (all versions) and WSS (all versions). Coverage based on samples observed so far. This protection is expected to be expanded over the next few days as viable exploitation attempts are seen.
    • Minimum DAT: V3 DAT (3564)
    • Detection names: Exploit-CVE2018-8653 and Exploit-CVE2018-8653.a
  • VSE (8.8+). Coverage based on samples observed so far. This protection is expected to be expanded over the next few days as viable exploitation attempts are seen.
    • Minimum DAT: V2 DAT (9113)
    • Detection names: Exploit-CVE2018-8653 and Exploit-CVE2018-8653.a

Content summary

  • DATs: V2 DAT (9113), V3 DAT (3564)
  • Generic Buffer Overflow Protection Signature ID 428

MITRE score

The base score (CVSS v3.0) for this vulnerability is 7.5 (High) with an impact score of 5.9 and an exploitability score of 1.6.

Conclusion

CVE-2018-8653 targets multiple versions of Internet Explorer and other applications that rely on the same scripting engine. Attackers can execute arbitrary code on unpatched hosts from specifically crafted web pages or JavaScript files. Even though the bug was recently fixed by Microsoft, we can expect exploit kits to soon deploy a weaponized version of this critical vulnerability, leveraging it to target remaining unpatched systems. The technical analysis in this post should provide enough information for defenders to ensure their systems will withstand the threat and to know which primitives to look for as an entry point for the attack. McAfee security products can be leveraged to provide specific “virtual patching” for this threat until full software patches can be deployed, while current generic buffer overflow protection rules can be used to fingerprint exploit attempts against this and similar vulnerabilities.

The post IE Scripting Flaw Still a Threat to Unpatched Systems: Analyzing CVE-2018-8653 appeared first on McAfee Blogs.

‘McAfee Labs Threats Report’ Highlights Cryptojacking, Blockchain, Mobile Security Issues

As we look over some of the key issues from the newly released McAfee Labs Threats Report, we read terms such as voice assistant, blockchain, billing fraud, and cryptojacking. Although voice assistants fall in a different category, the other three are closely linked and driven by the goal of fast, profitable attacks that result in …

The post ‘McAfee Labs Threats Report’ Highlights Cryptojacking, Blockchain, Mobile Security Issues appeared first on McAfee Blogs.

As we look over some of the key issues from the newly released McAfee Labs Threats Report, we read terms such as voice assistant, blockchain, billing fraud, and cryptojacking. Although voice assistants fall in a different category, the other three are closely linked and driven by the goal of fast, profitable attacks that result in a quick return on a cybercriminal’s investment.

One of the most significant shifts we see is that cryptojacking is still on the rise, while traditional ransomware attacks—aka “shoot and pray they pay”—are decreasing. Ransomware attacks are becoming more targeted as actors conduct their research to pick likely victims, breach their networks, and launch the malware followed by a high-pressure demand to pay the ransom. Although the total number of ransomware samples has fallen for two quarters, one family continues to spawn new variants. The Scarab ransomware family, which entered the threat landscape in June 2017, developed a dozen new variants in Q2. These variants combined make up more than 50% of the total number of Scarab samples to date.

What spiked the movement, starting in fall 2017, toward cryptojacking? The first reason is the value of cryptocurrency. If attacker can steal Bitcoins, for example, from a victim’s system, that’s enough. If direct theft is not possible, why not mine coins using a large number of hijacked systems. There’s no need to pay for hardware, electricity, or CPU cycles; it’s an easy way for criminals to earn money. We once thought that CPUs in routers and video-recording devices were useless for mining, but default or missing passwords wipe away this view. If an attacker can hijack enough systems, mining in high volume can be profitable. Not only individuals struggle with protecting against these attacks; companies suffer from them as well.

Securing cloud environments can be a challenge. Building applications in the cloud with container technology is effective and fast, but we also need to create the right amount of security controls. We have seen breaches in which bad actors uploaded their own containers and added them to a company’s cloud environment—which started to mine cryptocurrency.

New technologies and improvements to current ones are great, but we need to find the balance of securing them appropriately. Who would guess to use an embedded voice assistant to hack a computer? Who looks for potential attack vectors in new technologies and starts a dialog with the industry? One of those is the McAfee Advanced Threat Research team, which provides most of the analysis behind our threats reports. With a mix of the world’s best researchers in their key areas, they take on the challenge of making the (cyber) world safer. From testing vulnerabilities in new technologies to examining malware and the techniques of nation-state campaigns, we responsibly disclose our research to organizations and the industry. We take what we learn from analyzing attacks to evaluate, adapt, and innovate to improve our technology.

The post ‘McAfee Labs Threats Report’ Highlights Cryptojacking, Blockchain, Mobile Security Issues appeared first on McAfee Blogs.

McAfee Opens State-of-the-Art Security Research Lab in Oregon

McAfee’s Advanced Threat Research team has operated from several locations around the world for many years. Today we are pleased to announce the grand opening of our dedicated research lab in the Hillsboro, Oregon, office near Portland. Although we hav…

McAfee’s Advanced Threat Research team has operated from several locations around the world for many years. Today we are pleased to announce the grand opening of our dedicated research lab in the Hillsboro, Oregon, office near Portland. Although we have smaller labs in other locations, the new McAfee Advanced Threat Research Lab was created to serve two purposes. First, it gives our talented researchers an appropriate work space with access to high-end hardware and electronics for discovery, analysis, automation, and exploitation of vulnerabilities in software, firmware, and hardware. Second, the lab will serve as a demo facility, where the Advanced Threat Research team can showcase current research and live demos to customers or potential customers, law enforcement partners, academia, and even vendors.

The lab has been a labor of love for the past year, with many of the team members directly contributing to the final product. Visitors will have the unique opportunity to experience live and recorded demos in key industry research areas, including medical devices, autonomous and connected vehicles, software-defined radio, home and business IoT, blockchain attacks, and even lock picking! Our goal is to make vulnerability research a tangible and relatable concept, and to shed light on the many security issues that plague nearly every industry in the world.

Much of the research highlighted in the lab has been disclosed by McAfee. Links to recent disclosures from the Advanced Threat Research team:

Articles

Podcasts

Security researcher Douglas McKee prepares his demo of hacking a medical patient’s vitals. 

Onsite visitors will have the opportunity to solve a unique, multipart cryptographic challenge, painted on our custom mural wall in the lab. Those who are successful will receive an Advanced Threat Research team challenge coin! We will soon have an official video from the lab’s opening event online.

The post McAfee Opens State-of-the-Art Security Research Lab in Oregon appeared first on McAfee Blogs.

‘Insight’ into Home Automation Reveals Vulnerability in Simple IoT Product

Eoin Carroll, Charles McFarland, Kevin McGrath, and Mark Bereza contributed to this report. 
The Internet of Things promises to make our lives easier. Want to remotely turn lights and appliances on and off and monitor them online? A “smart plug,” a Wi-…

Eoin Carroll, Charles McFarland, Kevin McGrath, and Mark Bereza contributed to this report. 

The Internet of Things promises to make our lives easier. Want to remotely turn lights and appliances on and off and monitor them online? A “smart plug,” a Wi-Fi–connected electric outlet, is one simple method. But IoT devices can turn into attack vectors if they are not properly secured.

The McAfee Labs Advanced Threat Research team is committed to uncovering security issues in both software and hardware to help their developers provide safer products for businesses and consumers. We recently investigated a consumer product produced by Belkin. Our research into the Wemo Insight Smart Plug led to the discovery of an unreported buffer overflow in the libUPnPHndlr.so library. This flaw, CVE-2018-6692, allows an attacker to execute remote code. Following our responsible disclosure policy, we reported this research to Belkin on May 21.

Can this vulnerability lead to a useful attack? A smart plug by itself has a low impact. An attacker could turn off the switch or at worst possibly overload the switch. But if the plug is networked with other devices, the potential threat grows. The plug could now be an entry point to a larger attack. Later in this report, we will look at one possible attack.

Exploring the attack surface

Following the manual’s advice, the team used the Wemo phone application to set up the smart plug. We were able to remotely turn the outlet on and off. We then tested the software, including port scanning, monitoring normal network traffic, and reading online research. The Wemo listens on Universal Plug and Play (UPnP) ports TCP 49152 and 49153. The manuals, disassembly images, and the general-purpose programming language (GPL) were all online; they provided information on CPU architecture, the operating system, and applications.

We turned to the hardware and disassembled the device. We identified chips on the main board, found headers for communicating with the device, and pulled the memory off flash. Our online research provided datasheets for each of the chips on the board.

We found universal asynchronous receiver-transmitter (UART) pads on the board and confirmed them with the documentation. We soldered wires to these headers to discover if they were actively transmitting. To test communication with the device, we used an Exodus XI Breakout board, shown below:

After brute-forcing the baud rate, we were able to get debug information via the UART interface. The UART also provided a login prompt; however, neither online research nor simple guessing led us to a working password.

Extraction and firmware analysis

The flash chip discovered on the board was a Maxronix MX25L12835F, which is supported by flashrom, a well-known open-source tool for extracting firmware. Using flashrom and the XI Breakout board, we extracted the firmware from the Wemo device. After we obtained the original firmware image shipped with the device, we updated it using the Wemo mobile application. Once the device was updated, we again extracted the firmware from the device, providing us with a second image. We ran basic sanity checks with the new firmware to ensure our earlier software reconnaissance had not changed.

With the firmware extracted, we analyzed the firmware using binwalk, an open-source binary analysis tool. Binwalk extracted the file system from the firmware for further inspection. Access to the file system allowed us to review system configuration and access binaries.

Finding a vulnerability 

Network or remote vulnerabilities are more dangerous than local flaws, so we took a close look at the UPnP ports listening on the local network. During this testing phase our lead analyst was taking a class on Exodus Intelligence Embedded Exploitation. One of the class instructors, Elvis Collado (@b1ack0wl) was developing a UPnP fuzzer and offered to assist our efforts. Using this tool we started fuzzing the open UPnP ports, while monitoring the UART interface on the Wemo. After a short time we saw a crash on the UART interface.

11:37:16.702 stuntsx0x46ac6 STUN client transaction destroyed
sending SIGSEGV to wemoApp for invalid write access to
464d4945 (epc == 2ac1fb58, ra == 2ac1fccc)
Cpu 0
$ 0 : 00000000 00000001 0000006d 464d4945
$ 4 : 31d2e654 31d2e770 00000003 00000001
$ 8 : 0000007c fffffff8 00000007 00000002
$12 : 00000200 00000100 00000807 00000800
$16 : 31d2e6f0 31d2e898 004a1cb8 00000002
$20 : 31d2e638 31d2e6c0 004a1388 31d2e640
$24 : 00000400 2ac1fb30
$28 : 2ac77d40 31d2e600 31d2e648 2ac1fccc
Hi : 00000008
Lo : 00000000
epc : 2ac1fb58 Tainted: P
ra : 2ac1fccc Status: 0100fc13 USER EXL IE
Cause : 8080000c
BadVA : 464d4945
PrId : 0001964c
Modules linked in: softdog rt_rdm rt2860v2_ap(P) raeth
Process wemoApp (pid: 2157, threadinfo=80fa0000, task=802c87f0)
Stack : 2a0000d0 fffffffe 31d2e6f0 31d2e770 31d2e76f 31d2e6f0 31d2e6f0 31d2e770
00000000 31d2e604 00000000 00000000 2ac77d40 00000000 4f464751 4a484d4c
4e444241 47454f49 50464658 45414d42 43445044 464d4945 5552414c 46495048
4b524141 41445a4f 44534e4a 4e4e494c 44434357 494a4855 44515455 44494b45
55584a44 584e4f52 545a5247 51545954 595a4c42 4e594a45 484f5158 46474944

Call Trace:

Code: 80a20000 50480004 a0600000 <5440fffa> a0620000 a0600000 10a00006 24840004 24a50001
thready: Destructor freeing name “ChildFDTask”.
Aborted

After repeating and closely observing the experiment several times, we determined that the crash was caused by the following packet:

POST /upnp/control/basicevent1 HTTP/1.1
Host: 192.168.225.183:49154
User-Agent: python-requests/2.9.1
Accept: */*
Connection: keep-alive
SOAPAction: “urn:Belkin:service:basicevent:1#UpdateInsightHomeSettings”
Content-Type: text/xml
Accept-Encoding: gzip, deflate
Content-Length: 3253

<?xml version=”1.0″ ?><s:Envelope s:encodingStyle=”http://schemas.xmlsoap.org/soap/encoding/” xmlns:s=”http://schemas.xmlsoap.org/soap/envelope/”><s:Body><b1ack0wl_ns:UpdateInsightHomeSettingsxmlns:b1ack0wl_ns=”urn:Belkin:service:basicevent:1″><EnergyPerUnitCost>210</EnergyPerUnitCost><Currency>236</Currency><EnergyPerUnitCostVersion>KWWZWIVYBQZKDGSSAAPBCQVQQFAVYZEOEUFIDXXQPDYGESTOD
GIJFERXZNMYAFJQLUZPSIJXFQSPADCRIVHDAJLLPQMPLAVECIQUWLXDLIGPLBKCROGPOCVUI
KTSLIIXULOEBVFKWIERCFGHWHCBBDLWFBKBZXAVGRKTDALDNRPOFQJDXAEOC(…snip…)XHU
OUZPCHUBFGLLWSJBFYFOMCGZZMJIQIUVCDETFBRBZVDVKNBVZFBRSVBSZPAYKZYNQZEQPDV
DWSZNDUPUDCPAVWNFBFBTYMXTBNCWTBJPKORUBHBSCQBPOPOBZNVADMGWRI
</EnergyPerUnitCostVersion></b1ack0wl_ns:UpdateInsightHomeSettings></s:Body></s:Envelope>

For space reasons some of the payload has been removed. (The original data in “EnergyPerUnitCostVersion” was 2,828 characters.) After examining the crash data and the packet, this appears to be a standard buffer overflow, in which data is being overwritten onto the stack. We continued fuzzing, now focused on the “EnergyPerUnitCost” field and found we needed only 32 characters to crash the application.

Although the crash dump provides us with a lot of good information, there is still a lot we do not know. For example, the crash occurs in the “WemoApp” and provides us an offset, but what is the base address of this library? What has been overwritten on the stack? Without access to the application during runtime these questions are difficult to answer. Because we obtained the file system earlier, we could statically analyze the WemoApp binary; but we would still be unable to determine the exact point of the crash easily.

To answer these questions we needed to take one of two paths. We could virtualize the Wemo firmware or binary to continue testing; or if we could determine the root password on the UART interface, there is a chance we could debug on the device itself. Generally, virtualizing firmware is not simple and can sometimes lead to inaccurate test results. It is better to debug on the device. With all the information we found during reconnaissance, it seemed promising that we could bypass the root password. (We did spend some time attempting to virtualize the WemoApp—with no success.)

Bypassing the root password

From the extracted file system, we learned the Wemo runs the embedded Linux system OpenWRT, with the user account information held in either the standard /etc/passwd or /etc/shadow files. We extracted the hash for the root password from /etc/passwd and submitted it to a cracking rig. This method proved ineffective in a reasonable amount of time.

With our ability to read the flash chip we had a good chance to write to the chip. Barring any checksum or validations done on the firmware, we might be able to replace the /etc/passwd file with a known password.

To test this theory, we would have to repack the firmware. Since the GPL for the Wemo is public, we chose to use the same tools used by the developers. Using the GPL, we compiled the same version of squash tools 3.0 with Izma and repackaged the firmware file system with a modified /etc/passwd file. We added padding to ensure the firmware section was the same size as the original. We then used “dd” to insert the new file system segment into the firmware binary. During this process, we discovered that using binwalk to extract the firmware prevented us from correctly repackaging the firmware. We used “dd” with the information provided by binwalk to extract the correct section of the firmware binary for repackaging.

With a new firmware binary in hand, we used the XI Breakout board and flashrom to write the firmware to the flash chip on the board. After rebooting the device, we were able to log in using the new password.

Analyzing the crash 

With root access on the Wemo, we could gather more information about the crash during the UPnP fuzzing. First, we needed to compile the tools required to perform more in-depth analysis for this specific architecture. Using the GPL, we compiled gdbserver and gdb for the device. The Wemo had a large amount of installed tools, such as “wget,” making it simple to add files. We downloaded and executed the tools from the /tmp directory.

After a large amount of trying, we failed to get gdb running directly or remotely with the device. So we used gdbserver, in conjunction with Interactive Disassembler Pro, for all debugging. With the debugger connected, we sent the packet causing the crash and saw the exact location of the crash. A segmentation fault occurred at address 0x2AC15B98. From the memory layout from the Linux “proc” directory, we determined his memory address resides in library libUPnPHndlr.so.

2abf3000-2ac4d000 r-xp 00000000 1f:02 82 /rom/lib/libUPnPHndlr.so

Because the crash was caused by a UPnP packet, it was logical to find the crash inside this library . With the base address 0x2abf3000, we calculated the offset for static analysis in IDA to be 0x22b98.  At this address, we found the following:

LOAD:00022B70  # =============== S U B R O U T I N E =======================================

LOAD:00022B70

LOAD:00022B70

LOAD:00022B70                 .globl TokenParser

LOAD:00022B70 TokenParser:                             # CODE XREF: ProcessEnergyPerunitCostNotify+84↓p

LOAD:00022B70                                          # DATA XREF: LOAD:00004210↑o …

LOAD:00022B70                 beqz    $a1, locret_22BC0

LOAD:00022B74                 move    $a3, $zero

LOAD:00022B78                 move    $a3, $zero

LOAD:00022B7C                 b       loc_22BB4

LOAD:00022B80                 li      $t0, 0x7C  # ‘|’

LOAD:00022B84  # —————————————————————————

LOAD:00022B84

LOAD:00022B84 loc_22B84:                               # CODE XREF: TokenParser+28↓j

LOAD:00022B84                 addiu   $a1, 1

LOAD:00022B88                 addiu   $v1, 1

LOAD:00022B8C

LOAD:00022B8C loc_22B8C:                               # CODE XREF: TokenParser+48↓j

LOAD:00022B8C                 lb      $v0, 0($a1)

LOAD:00022B90                 beql    $v0, $t0, loc_22BA4

LOAD:00022B94                 sb      $zero, 0($v1)

LOAD:00022B98                 bnezl   $v0, loc_22B84

LOAD:00022B9C                 sb      $v0, 0($v1)

LOAD:00022BA0                 sb      $zero, 0($v1)

LOAD:00022BA4

LOAD:00022BA4 loc_22BA4:                               # CODE XREF: TokenParser+20↑j

LOAD:00022BA4                 beqz    $a1, locret_22BC0

LOAD:00022BA8                 addiu   $a0, 4

LOAD:00022BAC                 addiu   $a1, 1

LOAD:00022BB0                 addiu   $a3, 1

LOAD:00022BB4

LOAD:00022BB4 loc_22BB4:                               # CODE XREF: TokenParser+C↑j

LOAD:00022BB4                 slt     $v0, $a3, $a2

LOAD:00022BB8                 bnezl   $v0, loc_22B8C

LOAD:00022BBC                 lw      $v1, 0($a0)

LOAD:00022BC0

LOAD:00022BC0 locret_22BC0:                            # CODE XREF: TokenParser↑j

LOAD:00022BC0                                          # TokenParser:loc_22BA4↑j

LOAD:00022BC0                 jr      $ra

LOAD:00022BC4                 move    $v0, $a3

LOAD:00022BC4  # End of function TokenParser

 

Because the developers left the binary unstripped, we can name this function TokenParser. The segmentation fault occurs at a branch instruction; however, in MIPS the delay instruction is executed before the branch occurs. Thus the instruction at 0x22B9C is causing the crash. Here the application attempts to load what is at the address stored in $v1 and place it in $v0. Taking a look at the registers, we find the data from our packet in XML tags “EnergyPerUnitCostVersion” is in $v1, leading to an “invalid write access” segmentation fault error.

After statically analyzing the function, it appears to copy data from one section to another, looking three times for a 0x7C or “|” character. If it never finds the “|,” it keeps copying into a statically defined buffer. To fully understand why the overwrite occurs, let’s take a look at the stack as we step through the function:

2EF17630 2AC692F0 MEMORY:2AC692F0
2EF17634 00000000 MEMORY:saved_fp
2EF17638 34333231 MEMORY:34333231 ← previously copied data
2EF1763C 00000035 MEMORY:retaddr+31  ← next byte will be written at 0x2EF1763D
2EF17640 00000000 MEMORY:saved_fp  ← zeroed out memory prepared for the copy
2EF17644 00000000 MEMORY:saved_fp
2EF17648 00000000 MEMORY:saved_fp
2EF1764C 00000000 MEMORY:saved_fp
2EF17650 2EF17638 MEMORY:2EF17638 ← start writing at this address; can be overwritten

As the function copies data onto the stack, it eventually copies over the address for the original buffer. Once this address is overwritten, the function attempts to write the next byte at the new value, in this case is an invalid address. This overflow gives an attacker two exploitable vectors: a write-what-where condition allows an attacker to write data to an arbitrary location in memory; by continuing to overwrite data on the stack, an attacker can overwrite the $RA register or return address for the calling function, providing the attacker control of the execution flow.

Writing the exploit

Now that that we understand the vulnerability, can we exploit it? Because this is a standard buffer overflow, we need to answer two questions. How much room is available on the stack, and are there any “bad” bytes that cannot make it onto the stack? To determine the available room, we can examine how much of the payload makes it onto the stack if we repair the address overwritten on the stack with a valid address. We learned only 91 bytes can be written onto the stack.

The next step is to determine if there are any “bad” bytes. After running a few tests, we noticed that only ASCII characters can make it onto the stack. Before the vulnerable code is executed, the packet is parsed by the open-source XML parser “mxml.” This library follows the standard of allowing only ASCII and Unicode characters to exist between tags.

This standard is very problematic for both shellcode and return-oriented programming (ROP) techniques because both memory address and shellcode tend to use mostly nonreadable characters. We could use several techniques to combat room on the stack; however, due to the hard limitation on characters that will pass through the XML sanitization process, it would be best to use functions that are already loaded into memory. One method that does not require extensive shellcode is to use a “return to libc” attack to execute the system command. Because the system call typically takes a string as a parameter, this might pass through the filter. Because the Wemo does not use address space layout randomization, if we use ROP it would be theoretically possible to make a call to system without needing to pass additional shellcode through the XML filter.

We still face a major challenge: Only addresses comprising entirely ASCII characters can pass through the XML filter. This drastically limits the potential for finding usable gadgets. We used IDA to see where libc and system are loaded into memory, and found two implementations: in libuClibc-0.9.33.2.so at address 0x2B0C0FD4; and in libpthread-0.9.33.2.so at address 0x2AD104F4. However, neither of these addresses meet the requirements to pass through the XML filter. Thus even if we could create an ROP chain, we would not be able to send just the address for system in the packet.

Addresses with bad characters are not a new problem for exploit development. One of the most common bypasses is to use addition or subtraction ROP gadgets to create the required address in a register and call that register. Again, however, we face the limitation on which operands can be used for this addition or subtraction equation due to the XML filter.

After studying the memory layout, we discovered that libuClibc-0.9.33.2.so sits at a memory location with addresses that can bypass the XML filter. We were fortunate that this is a large library, providing a decent list of addresses, because it is the only library in such a space. With this discovery, the team created a tool to assist with the creation of this exploit. The tool pulls out all possible ROP gadgets with usable memory addresses and determines if an addition or subtraction equation could call one of the two system calls found in memory, using only the values that will bypass the filter. The address for system in libuClibc-0.9.33.2.so, 0x2B0C0FD4, did not have any usable operands. However, 0x2AD104F4 did. We found several “filter-proof” operands that when added together equaled 0x2AD104F4.

We employed our tool’s output for all possible ROP gadgets that bypass the filter to build an ROP chain, which uses an addition instruction to create the final address for system and stores it in $s0. After the addition, another gadget moves the address for system into $t9 and calls system. This final gadget also moves an address that can be controlled from the stack into the register holding the parameter for the system call. The entire ROP chain consists of only three gadgets, which easily fit in the stack space provided by the buffer overflow. 

 

Piecing everything together 

Earlier we discovered two attack techniques that can be used with this vulnerability: a write-what-where, and overwriting the return address on the stack. Each packet sent can use each technique once. To get a parameter to the system call, we must use write-what-where to place the parameter in a writable memory address and pass this address to system. Fortunately, this vulnerable application sets aside a large amount of writable memory that is never used, and in a range accessible to our limited set of addresses that bypass the filter. Unfortunately, the ROP chain that calls system requires the use of write-what-where to handle extra instructions in one of the ROP gadgets. This means that two packets are required to execute the exploit: one to write the parameter for system into memory, and a second to make the call to system. Thus it is important that the first packet exits cleanly and does not crash the program.

One way to execute cleanly is to use three well-placed pipes (“|”) inside the payload to stop writing and exit TokenParser at the appropriate time. It is also important to not overwrite the RA pointer so the program can continue normal execution after the packet is received. Then the second packet is sent containing the ROP chain calling system with the address of the parameter written by the previous packet. 

Payload 

With the discovery of a valid ROP chain that can call system, we must decide what system should call. Because system executes as root, we can gain complete control of the device. Our research has showed that the device has many Linux commands installed. We leveraged this earlier with wget to copy gdbserver to the device. An attacker could also call wget from system to download and execute any script. We explored further for installed applications and found NetCat, which could allow an attacker to write a script to create a reverse shell. An attacker could download a script using wget, and execute the script containing a NetCat command to create a reverse shell. We tested and proved this is one simple, effective method, opening a reverse shell as root. Attackers could choose many other methods to leverage this exploit and execute code. The following video demonstrates this exploit working with a reverse shell.

To illustrate, the team wrote an attack scenario. After the plug is compromised, it could use the built-in UPnP library to poke a hole in the network router. This hole creates a backdoor channel for an attacker to connect remotely, unnoticed on the network. In the following video, we used a remote shell to control a TCL smart TV connected to the network. The Roku API implementation on the TV uses simple unencrypted HTTP GET/POST requests to issue commands and does not authenticate the machine sending these commands, making remote control trivial. Using the Wemo as a middleman, the attacker can power the TV on and off, install or uninstall applications, and access arbitrary online content. Smart TVs are just one example of using the Wemo to attack another device. With the attacker having established a foothold on the network and able to open arbitrary ports, any machine connected to the network is at risk. Because attacks can be conducted through the Wemo and the port mappings generated using this exploit are not visible from the router’s administration page, the attacker’s footprint remains small and hard to detect.

Conclusion 

Discoveries such as CVE-2018-6692 underline the importance of secure coding practices on all devices. IoT devices are frequently overlooked from a security perspective; this may be because many are used for seemingly innocuous purposes such as simple home automation. However, these devices run operating systems and require just as much protection as desktop computers. A vulnerability such as we discovered could become the foothold an attacker needs to enter and compromise an entire business network.

One goal of the McAfee Advanced Threat Research team is to identify and illuminate a broad spectrum of threats in today’s complex and constantly evolving landscape. Through analysis and responsible disclosure, we aim to guide product manufacturers toward a more comprehensive security posture.

The post ‘Insight’ into Home Automation Reveals Vulnerability in Simple IoT Product appeared first on McAfee Blogs.