Exploiting MS15-034 with PowerShell

Updates have been made available to this code to support SSL. See the update here.


On Thursday morning, I woke up to an extremely busy Twitter stream; the topic which that was on everyone’s’ lips was Microsoft Security Bulletin MS15-034.

MS15-034 is a critical security bulletin impacting HTTP.SYS, which forms a core component of IIS and a number of other Windows roles and features. The vulnerability described in the bulletin is a Remote Code Execution (RCE) however at the time of the publication of this post, only a Denial of Service (DOS) of the system has been achieved. There are a number of claimed RCE pieces of code on sale, yet none have been verified.

Over the days since the original release of the bulletin and its associated fixes, things have moved quite quickly. Simple detection (more) and exploitation code had been developed, as well as more complex pieces and even a Metasploit module. Now it is fine for those of us who have Linux systems, or even maybe those who have Windows ports of perl, python, curl or wget installed to use a number of these scripts/examples that are out there, however I feel it is important that this be presented in a way that is accessible and understandable by the average Windows administrator.

Chris Campbell (@obscuresec), put together some PowerShell code that would allow administrators to determine if a system was vulnerable. Unfortunately, there were some issues with this code that means it isn’t as effective as it could be. Firstly, Chris’ code doesn’t report if any other HTTP errors are generated, for example, if you specify an invalid page, the code wouldn’t alert you to the HTTP 404 that would be returned. The next issue is that a non-vulnerable system returns a HTTP 400 after the patch, something the code doesn’t pick up on. Finally, the range header values specify do not match what has been specified in other pieces of code. I felt we needed not only PowerShell code to test if a server was vulnerable, but that it would be interesting to see if we could also exploit a vulnerable server.

Now it should be noted, that you simply can't use the .Net WebRequest class to specify the appropriate “Range” header values, you need to use the TCPClient class and run at a lower level. This is more of a separate discussion I will leave for a later post.

Over the course of past few days, I developed PowerShell code, heavily inspired by the Metasplout module, to allow for the testing and exploitation of MS15-034. This code is contained in the module, MS15034.psm1 up on the Posh Security GitHub. There are two functions which will be of interest; Test-MS15034, which allows for the testing of servers, and Invoke-MS15034DOS which is capable of performing a denial of service against a specified target.

Testing

The CMDLet Test-MS15034 requires the specification of a computer name or IP address, and optionally a port number, and then 3 different parameter sets:

  1. Specifying the -Windows2008 parameter
  2. Specifying the -Windows2012 parameter  
  3. Specifying a custom HTTP path with the -ServerPath parameter

The first two are simply to simply the testing against lab environments, as they will connect to the URL of the format http://<Computer>/welcome.png and http://<Computer>/IIS-85.png respectively. The third option is to specify your own HTTP path, which is something you are more likely to do in a real world scenario. You can specify any file or structure using -ServerPath, examples could be:

  • /index.html
  • /CompanyLogo.png
  • /images/logo.jpg

Let’s look at some examples (these may not display correctly via RSS)!

1) Testing a Windows 2008 server and determining that it is vulnerable:

2) Testing a Windows 2012 server and determining that it is vulnerable:

3) Testing a Windows 2012 server and determining that it is not vulnerable :

4) Testing a server using a custom server path and determining that it is vulnerable:

5) Testing a server and specifying the wrong operating system (or the default files do not exist):

6) Testing a server using a custom server path, which doesn't exist:

This CMDLet will connect to the URL determined by the parameters, specifying the header Range: bytes=0-18446744073709551615. If the response from the server is a HTTP 416, then it is vulnerable, if the response is HTTP 400, then the server is not vulnerable. Other errors will be displayed and managed accordingly. 

Exploitation

Now let’s take an attack to the next level and take the server down! The CMDLet Invoke-MS15034DOS will do the trick for us. This CMDLet works much like the Metasploit module. The CMDLet accepts the same parameters as Test-MS15034, however it will begin by testing if the server is vulnerable, and if so, will then perform a denial of service.  The denial of service will be performed by specifying the header Range: bytes=0-18446744073709551615. 

 

In the examples that follow, I am simply using the default out-of-the-box images as the addresses, much like in the previous tests.

1) Invoking a denial of service against a Windows 2012 (R2) server:

2) Invoking a denial of service against a Windows 2008 (R2) server:

3) What happens if you try to invoke a denial of service against a patched server:

Next is a video of Invoke-MS15034DOS against an unpatched Windows 2012 R2 server. Note how quickly the server is taken down. I think it makes a nice alternative to Restart-Computer.

It should be noted that my code will only support HTTP and not HTTPS. I could develop support for HTTPS, but I suspect that in most environments, testing if a server is vulnerable via HTTP will be sufficient.

You can download my module from my GitHub repository MS15034, a zip file can be found here.

I really hope people will find this code useful. I will be putting together some follow up posts on this topic, including some observations around the issue and how I developed the code.

Kieran Jacobsen