An Analysis Of MS15-034

Written on:April 18, 2015
Comments
Add One

Introduction

By now you’ve undoubtedly heard about MS15-034. The following is a collection of my cursory research and thoughts on this vulnerability.

In addition, here is a small list of related resources, some of which I also reference in the sections that follow:

A brief overview of the vulnerability

According to the published Microsoft Security Bulletin, MS15-034 is a remote code execution vulnerability caused by HTTP.sys improperly parsing specially crafted HTTP requests. Specifically this exploit can be triggered using the Range header of an HTTP request, causing an Integer overflow. While the bulletin indicates Remote Code Execution is possible (and as such rates this vulnerability as Critical), so far I have only been able to generate a Denial of Service condition and have not yet seen any RCE code in the wild (though I’m sure someone is working hard at it). Before I get into the details of the vulnerability, let’s take a quick look at HTTP.sys and its purpose.

What is HTTP.sys?

HTTP.sys (aka the HTTP Protocol Stack) is a Windows kernel-mode device driver which, as stated in Microsoft’s Introduction to IIS Architectures, “listens for HTTP requests from the network, passes the requests onto IIS for processing, and then returns processed responses to client browsers”. It is responsible for providing Kernel-mode caching, Kernel-mode request queuing, and request pre-processing and security filtering.

Kernel-mode caching which improves performance by serving all cached content requests directly from kernel-mode, appears to be the culprit in this vulnerability. Although Microsoft does cite disabling IIS Kernel caching as a possible workaround, it may cause too much performance degradation on production web servers to be very practical.

While it’s clear that MS web servers running modern IIS versions are the primary affected group, keep in mind the the HTTP Protocol Stack implemented by Http.sys is used by more than just IIS so other applications may be affected as well.

What is the Range Header?

I mentioned earlier that this vulnerability can be triggered via the Range header. The Range header is used in an HTTP request to return a portion (or range of bytes) of a given resource. Take for example, the following requests that illustrate how to obtain a portion of Google’s humans.txt file using the Range header.

ms15_034_15

The RFC does not require clients or servers to honor/support Range headers, though most do. It also allows for various formats of byte range specifications including a single range or set of ranges such as:

  • bytes=0-499,
  • bytes=500-999,
  • bytes=-500,
  • bytes=9500-,
  • bytes=0-0,-1,
  • bytes=500-600,601-999

I mention this because as Didier Stevens pointed out in his post, if you’re building IDS/IPS rulesets for detection/prevention of this exploit you need to take into account the various allowable methods of formatting this header.

A Deeper Dive

When I was researching this vulnerability, the first resource I came across was this nice write-up from the team at BeyondTrust. I encourage you to read it, but I’ll also replicate some of their findings here.

They start by analyzing this vulnerability in much the same way that I (and probably many others) did … by diffing the old and new HTTP.sys files. Here’s a shot of mine:

ms15_034_1

This is a view of the UlpParseRange function (unpatched HTTP.sys shown on the left, patched shown on the right), which after the update, has one key difference…an additional call to RtlULongLongAdd(). Although this is a slightly modified, 5 parameter version (vs. the 3 parameter version specified on MSDN), the intent of the added function is the same…to provide a validity check to prevent against Integer overflow conditions. The absence of this check in the unpatched version of HTTP.sys is what allows for the overflow condition at the heart of MS15-034.

So you can get a little better idea how this comes into play, take a look at the following:

ms15_034_3

You can see UlpParseRange is called by HlContentRangeHeaderHandler, when it needs to process the values passed via the Range header.

Now, taking a look at the UlpParseRange, you can see the location where the missing Integer Overflow condition check should be in the vulnerable version of HTTP.sys (top) and how it was addressed in the updated version via the addition of RtlULongLongAdd:

ms15_034_2

Unpatched HTTP.sys

 

ms15_034_4

Patched HTTP.sys w/ RtlULongLongAdd

If we step back even further, before getting to this point, UlpParseRange makes a call to UlpParseRangeNumber, which as its name implies, parses the numbers passed via the Range Header. This latter function actually makes its own calls to RtlULongLongAdd, though they don’t serve to provide any protection against the core Integer Overflow problem.

To give you an idea of what this looks like, I set breakpoints on each of the three functions and passed a Range header value of bytes=14-156. What will happen is the breakpoint for UlpParseRange will hit once (for the single range passed via the header). Following that breakpoint, UlpParseRangeNumber will hit twice (once for each number in the range — 14 and 156). After each UlpParseRangeNumber breakpoint, RtlULongLongAdd will trigger for each digit in the respective range number. That means it will hit twice for the number 14 and three times for the number 156.

Here is what that would look like:

0: kd> g
Breakpoint 0 hit
HTTP!UlpParseRange:

0: kd> g
Breakpoint 1 hit
HTTP!UlpParseRangeNumber:

0: kd> g
Breakpoint 2 hit
HTTP!RtlULongLongAdd:

0: kd> r
eax=00000001 ebx=8e2b0b08 ecx=0000000a edx=00000000 esi=00000031 edi=00000017
eip=8b176ebf esp=8e2b0aa8 ebp=8e2b0ad8 iopl=0 nv up ei pl zr na pe nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000246

0: kd> g
Breakpoint 2 hit
HTTP!RtlULongLongAdd:

0: kd> r
eax=00000004 ebx=8e2b0b08 ecx=0000000a edx=00000000 esi=00000038 edi=00000016
eip=8b176ebf esp=8e2b0aa8 ebp=8e2b0ad8 iopl=0 nv up ei pl zr na pe nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000246

0: kd> g
Breakpoint 1 hit
HTTP!UlpParseRangeNumber:

0: kd> g
Breakpoint 2 hit
HTTP!RtlULongLongAdd:

0: kd> r
eax=00000001 ebx=8e2b0b08 ecx=0000000a edx=00000000 esi=00000031 edi=00000014
eip=8b176ebf esp=8e2b0aa8 ebp=8e2b0ad8 iopl=0 nv up ei pl zr na pe nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000246

0: kd> g
Breakpoint 2 hit
HTTP!RtlULongLongAdd:

0: kd> r
eax=00000005 ebx=8e2b0b08 ecx=0000000a edx=00000000 esi=00000038 edi=00000013
eip=8b176ebf esp=8e2b0aa8 ebp=8e2b0ad8 iopl=0 nv up ei pl zr na pe nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000246

0: kd> g
Breakpoint 2 hit
HTTP!RtlULongLongAdd:

0: kd> r
eax=00000006 ebx=8e2b0b08 ecx=0000000a edx=00000000 esi=00000034 edi=00000012
eip=8b176ebf esp=8e2b0aa8 ebp=8e2b0ad8 iopl=0 nv up ei pl zr na pe nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000246

 

Once the numbers passed via the Range header are parsed by UlpParseRangeNumber, it returns to UlpParseRange, and the vulnerable portion of the function follows.

ms15_034_5

Let’s take a closer look at the above location 6EEF9 (highlighted) by passing a crafted Range header value. To demonstrate the simple mechanics of the vulnerable code, I’ll use an example range of 21845 – 18446744073709551615. The latter number is the largest possible value of a 64-bit unsigned Integer.

ms15_034_6

I chose the former simply for ease of demonstration as it equates to 5555h.

After parsing the provided Range header value, the code at loc_6EEF9 subtracts the lower range value (stored in EDI) from the upper range value (stored in EAX) and then adds 1.

ms15_034_8

ms15_034_7

By not properly checking the bounds of these values following the addition/subtraction, the codes leaves an opportunity for an overflow condition (if you’re unfamiliar with the concept of Integer Overflows you might refer to the following Wikipedia article: http://en.wikipedia.org/wiki/Integer_overflow).

So What?

Why is this bad? Well, according to Microsoft, this particular vulnerability can lead to remote code execution though Integer Overflows can be difficult to translate to robust/reliable RCE, I have certainly not yet been able to do so in my test environment, nor have I seen any such exploits circulating in the wild (yet). Even so, I (like many others) have been able to easily and reliably generate a denial of service condition by exploiting this vulnerability. The fact that it’s so easy to cause a DoS means you should remediate it as soon as possible.

Identifying Vulnerable Assets

You can perform a basic check on your server(s) to determine their vulnerability to this exploit. Simply make a request for a static resource (such as an image) and pass a range header with the values bytes=0-18446744073709551615. An unpatched, vulnerable server should respond with “Requested Range Not Satisfiable”

ms15_034_9

You can use an intercepting proxy (such as Burp), curl, or a custom script to generate such a request (I’ve provided one below). Note: modifying the lower number of the range to anything other than 0 risks causing a DoS condition on the target so use with caution! Which brings me to my next topic…

Causing a DoS

You can cause a Denial of Service condition by changing the lower value of the range. For example, the common example I’ve seen floating around the interwebs is Range: bytes=18-18446744073709551615. The number 18 is somewhat arbitrary and many other values will work, though it will also depend on the size of the resource your requesting.

I wrote a simple python script to both check for the presence of the vulnerability as well as exploit the DoS condition. For demonstration purposes it simply requests the /welcome.png file common to the Standard IIS installation on Windows 7 SP 1 (though this configurable).

I wrote this days ago to test/demo the exploit so it’s completely function over form. To use it in order to check if an asset is vulnerable simply specify the target url as follows:

ms15_034_10

I’ve also included a simple flag (-e) to automatically trigger the DoS condition — using a default range of 18-18446744073709551615 and assuming the presence of /welcome.png (both of which are configurable via CL options).

ms15_034_11

As stated earlier, modifying the range header by itself can trigger a DoS so use with caution!!!

ms15_034_12

What About Internal Servers?

Whenever there’s a web-based vulnerability, the first thing that most people think to patch are their public-facing/DMZ systems…and rightly so. Naturally, it’s recommended to patch all servers but priority absolutely lies with those that are public facing. They are going to have the most exposure and therefore the greatest risk for targeting. But what about your internal servers?

You may recall a post I did in October of last year called “Phishing for Shellshock” in which I demonstrated that it was trivial to target an organization’s internal servers using a phishing attack to exploit what many were considering an “external” vulnerability. While it’s technically possible to exploit MS15-034 in a similar manner, there are some key differences that made Shellshock more susceptible.

First, several of the header(s) available for use to exploit Shellshock (Accept, Accept-Language, etc) were not protected by CORS, meaning they could be used in a CSRF-style phishing attack in which a targeted user unknowingly executes malicious JavaScript in their browser that then delivers the exploit to the servers on their internal network. In the case of MS15-034, the Range header is in fact protected by CORS so the likelihood of a successful exploit is lower.

Second, Shellshock was a bit more attractive to exploit in that manner because it resulted in remote code execution.The beauty of the Shellshock phishing exploit was the targeted user didn’t need to do any parsing of the response from the exploited server since it would call directly back out to the attacker. So far, MS15-034, only results in DoS and apparently some limited and inconsistent Information Disclosure (though I have not been able to replicate).

So does that mean internal systems are completely safe from a phishing attack? Not necessarily. It’s not uncommon to see some relaxed CORS rules on the internal network (for both clients and servers) so keep that in mind when considering your own environment. Also, although there is no published RCE yet, it doesn’t mean one doesn’t exist (though it’s not necessarily easy given this is an integer overflow).

To demonstrate how this could work, I configured a test IIS server with some insecure, unrestricted response headers:

ms15_034_13

I then created this simple web page (a modified version of my Shellshock exploit):

Should the victim visit this page (via a phishing email perhaps), they will be treated to a trailer of the new Star Wars movie. At the same time, the embedded JavaScript will kick off a series of requests to their internal network (as dictated by the provided GET parameters) attempting to exploit this Range header vulnerability.

The corresponding phishing link would be formatted as follows: http://attackersite.com?s=192.168.0.0.&e3=255&e4=255

In this case, s is IP address at which to start exploiting and e3 and e4 are the values at which to stop exploiting for the third and fourth octet respectively. In the case of the above URL, the phishing target will attempt to exploit every asset from 192.168.0.0 to 192.168.255.255.

ms15_034_14

So how likely is this to actually be exploited on internal servers? Probably not very likely, especially if you’ve restricted CORS internally and have a trained user population that isn’t very susceptible to phishing. Either way, I think it’s important to always think of how exploits such as these could find their way into the internal network and ensure you’ve got a plan to patch all of your assets.

Conclusion

I hope this post provided some useful details and ideas regarding the MS15-034 vulnerability. As with any Critical, remotely executable vulnerability, I recommend you patch/mitigate as soon as possible.

Until next time,

Mike

peCloak.py – An Experiment in AV Evasion

Written on:March 9, 2015
pecloak25

Introduction I just wrapped up the Offensive Security Cracking The Perimeter (CTP) course and one of the topics was AV evasion. Although I write a lot of custom scripts and tools, when it comes to AV evasion, I typically rely on the tools and methods of others (Veil, powershell, python, custom shellcode). That said, the great thing about courses like CTP is they give me an excuse to investigate a topic that I haven’t…

Read more...

EggSandwich – An Egghunter with Integrity

Written on:February 12, 2015
eggsandwich6

Introduction A while back I introduced the EggSandwich in my tutorial on Egghunting as a means to implement some basic integrity checks into the traditional Egghunter and overcome the problem of fragmented / corrupted shellcode. I recently took the opportunity to update my implementation so it could accomodate shellcode of any size. The code and a brief explanation follows. What is the EggSandwich? I ran into a situation when developing an exploit for an…

Read more...

Developing a Security Assessment Program

Written on:December 19, 2014
appsec_process_04

Introduction Most organizations and are deploying new applications and technologies at a high rate and without a means to adequately assess them prior to implementation, it’s difficult to accurately gauge your organization’s risk. No matter what the size or industry, it’s imperative that an organization has a standardized and repeatable process for assessing the security of the IT solutions it implements.  My goal with today’s post is to provide some recommendations on…

Read more...

Exploiting MS14-066 / CVE-2014-6321 (aka “Winshock”)

Written on:November 29, 2014
ms14066_36

Introduction I think enough time has passed now to provide a little more detail on how to exploit MS14-066 schannel vulnerability (aka “Winshock”). In this post I won’t be providing a complete PoC exploit, but I will delve into the details on exactly how to trigger the heap overflow along with some example modifications to OpenSSL so you can replicate the issue yourself. This vulnerability was announced while I was on…

Read more...

Windows OLE RCE Exploit MS14-060 (CVE-2014-4114) – Sandworm

Written on:October 22, 2014
ms14_060_2

This recent exploit (dubbed “Sandworm”) took advantage of a vulnerability in which a specially crafted OLE object could allow remote code execution. In the case of the live sample exploit PPSX file I examined, it automatically downloaded the payload from a remote SMB share. I won’t rehash much of the details that others have covered but if you want to read more, here are some resources: Microsoft Security Bulletin: https://technet.microsoft.com/en-us/library/security/ms14-060.aspx Original Discovery by…

Read more...

Drupal 7 SQL Injection (CVE-2014-3704)

Written on:October 17, 2014
drupal_sqli_5

Introduction This vuln has been getting a lot of attention, and rightfully so. The good news is an update is available (and a supplemental patch has been released as well). The bad news is that it’s pre-auth SQLi. The basic problem is the way Drupal core 7.x versions prior to 7.32 construct a SQL query. Contrary to some claims, this is not a flaw in the use of prepared statements/parameterized queries, which…

Read more...

Phishing for Shellshock

Written on:October 10, 2014
phishing_shellshock_1

Introduction I thought I was done writing about Shellshock, but a recent discussion with some colleagues got me back on the topic. We were commenting about how organizations tend to react very quickly to patching external assets for a bug like Shellshock but many probably wait to patch internal assets due to a false sense of security. It got me thinking about how an external actor could exploit a bug like…

Read more...

Shellshock – Targeting Non-CGI PHP

Written on:September 30, 2014
shellshock_php_0

I’ve seen debates as to whether or not it’s possible to have an unpatched PHP server running in mod_php mode (i.e. not CGI) that is vulnerable to Shellshock. From my testing, the answer appears to be Yes…with some prerequisite conditions. First, the PHP application would have to be using Bash for its system commands — exec(), passthru(), system(), popen(), etc. This is pretty obvious since Shellshock is a Bash-specific vulnerability. Although PHP system command…

Read more...

The Search For Shellshock

Written on:September 28, 2014
shellshock_2

Introduction By now there are hundreds or even thousands of posts and articles about the Bash “Shellshock” vuln and more will be written tomorrow (and the next day …). With that in mind, this post will be fairly short and I won’t be rehashing what shellshock is or why it’s a problem. For that you can simply Google “shellshock” and you’ll find all you wanted to know and more. If you want…

Read more...