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:
- Specifying the -Windows2008 parameter
- Specifying the -Windows2012 parameter
- 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
Content From Vic .Net Presentation
Last week I had the wonderful pleasure of presenting to the Victorian .Net User Group. I want to thank Mahesh, the other organizers and SportsBet for the wonderful facilities.
I have been extremely lucky to present to a wide range of audiences on the security challenges that PowerShell brings to our organisations. From security groups to architecture to infrastructure and now development focused groups.
As promised, here is the content, code and links to more information.
You can download the PowerPoint slides here, or find them on SlideShare here.
If you want to take a look at the "malware" script that I created, you can find that up GitHub here. The repository includes two files, an example of the Excel spreadsheet which contains a macro that would infect a system, and then the SystemInformation.ps1, which is the actual "malware" that is the basis for all of my demonstrations.
I mentioned Matt Graeber's write up on PowerWorm, and this can be found here at his site, www.exploit-monday.com. Matt has rewritten the code to be more safe, as well as provide some tools to detect and remove PowerWorm infections and this can be found on his GitHub.
Another important set of resources are the 5 part series from the Microsoft's Hey Scripting Guy.
- Use PowerShell for Network Host and Port Discovery Sweeps
- Use PowerShell to Security Test SQL Server and SharePoint
- Use PowerShell to Discover Network Information from Shares
- Use PowerShell to Duplicate Process Tokens via P/Invoke
- Use PowerShell to Decrypt LSA Secrets from the Registry
I recommend reading the final two parts, I have made use of the code from these within SystemInformation.ps1.
Kieran
Please update your RSS subscriptions
This is just a quick public service announcement, if you subscribed to my blog back on the old domain name, aperturescience.su, then please update your readers settings to point to the new RSS feed address: http://www.poshsecurity.com/?format=rss
At the end of April my old domain, aperturescience.su will be switched off and I would hate for you to miss out on further content.
Thanks!
Kieran Jacobsen
Enabling Mobile Device Management with Office 365
Microsoft recently announced that they would be including a Mobile Device Management (MDM) platform as part of Office 365. What this means is that organisations, both small and large now have an extremely easy and powerful MDM available to them, without any additional charge to their Office 365 licencing. Administrators can manage Android, iOS and Windows Phone devices, and enforce various corporate policies and standards.
To support the new MDM functionality, you will need to create two new DNS records in each of your Office 365 domains. I have updated the Posh-Office365CloudFlare script to support the creation of these two additional records. You can create these records via the -MDMEnable parameter.
The process for creating the entries is as simple as:
Register-Office365.ps1 -CloudFlareApiToken <token> -CloudFlareEmailAddress <email> -Domain <domain> -MDMEnable
Just a quick note, I am yet to fully test out the new MDM functionality as none of my existing tenants have enabled for it yet.
Kieran Jacobsen
Upcoming Presentation at Victorian .Net User Group
I am excited to announce that I will be presenting PowerShell Shenanigans – Lateral Movement with PowerShell, to the Victorian .Net User Group.
This presentation will be an updated version of the one from CrikeyCon 2014, BIG and OWASP Brisbane.
Information about the session is listed below, and you can register here at Eventbrite.
PowerShell Shenanigans (Lateral Movement with PowerShell)
PowerShell, the must have tool and the long overlooked security challenge. Learn how PowerShell’s deep integration with the Microsoft platform can be utilized as a powerful attack platform within the enterprise space. Watch as a malicious actor moves from a compromised end user PC to the domain controllers and learn how we can begin to defend these types of attacks
About the Speaker
Specialising the automation of Windows Server environments, and with 10 years’ experience in the managed services and financial services sectors, Kieran Jacobson recently moved from sunny Brisbane to Melbourne to pursue a role as a Technical Lead with Readify. Kieran has always been a passionate member of the technical community, beginning as a Microsoft Student Ambassador and then as a presenter at a number of conferences including Infrastructure Saturday, CrikeyCon and Risky Business. Kieran maintains the Posh Security website, http://poshsecurity.com, with content ranging from automation, architecture, troubleshooting and software development.
Event Details
- When: 5:30 PM, Tuesday, 7th April 2015
- Where: Sportsbet, Level 15, 367 Collins Street, Melbourne
- RSVP: Register attendance at http://vicdotnet-apr2015.eventbrite.com.au
Automating Office 365 deployments in CloudFlare
A few weeks ago, I wrote about Posh-CloudFlare, a PowerShell module I created for managing CloudFlare hosted domains. Since then, I was working on extending an Office 365 deployment, and realized that what was needed was a script which could automate the configuration of new domains. With that in mind, I developed a new PowerShell script, Posh-Office365CloudFlare.
Let's understand the process for the addition and configuration of a new domain for Office 365.
The process starts with the Office 365 Portal. We navigate to the Domains section, click the "Add Domain" button, and after ignoring the introduction, we proceed to step 1. This step starts with us entering our domain name, let's use our old favorite contoso.com. Now we will be asked to verify that we own this domain, either through the creation of a TXT record or an MX record. The typical method is to use is that of a TXT record, created at the root of our desired domain with a value something like "MS=mx********".
After we create the domain, and the wizard successfully sees the appropriate record, we will be allowed to proceed to the next step. Step 2 isn't one that I usually make use of. I typically don't want to modify my users email domains, nor do I want to add new users at this time. I skip this step and move straight on to step 3.
Step 3 starts with another quick introduction screen, and then we will be asked if we would like the DNS for this domain to be managed by Microsoft. Obviously, we are going to answer no and move on. Finally, we reach an important step, we are asked what we want to do with this domain. First, "Outlook for email, calendar, and contacts", or in other words, email; the second, "Lync for instant messaging and online meetings", which is kind of obvious.
If you select “Outlook for email, calendar, and contacts”, then we will be told to create the following records in contoso.com:
- MX - @.contoso.com - which points to contoso-com.mail.protection.outlook.com (priority 0)
- CNAME – autodiscover.contoso.com – which points to autodiscover.outlook.com
- CNAME – msoid.contoso.com – which points to clientconfig.microsoftonline-p.net
- TXT – @.contoso.com – which contains a SPF record
If you select “Lync for instant messaging and online meetings”, then we will need to create the following records for contoso.com:
- CNAME - sip.contoso.com - which points to sipdir.online.lync.com
- CNAME - lyncdiscover.contoso.com - which points to webdir.online.lync.com
- CNAME – msoid.contoso.com – which points to clientconfig.microsoftonline-p.net
- SRV - _sip._tls.contoso.com - with its appropriate port, weight, priority and target
- SRV - _sipfederationtls._tcp.contoso.com - with its appropriate port, weight, priority and target
Reviewing this list of records, we will notice that the only record that changes for each domain is the MX record. The record consists of the domain name we want to add, with dashes replacing the original dots in the domain name. As you can see in the above example, cotoso.com's MX record points to contoso-com.mail.protection.outlook.com, where as awesomecompany.net would point to awesomecompany-net.mail.protection.com.
What about some records that could actually help our users? What if I said we could redirect sub domains of our own to the Outlook Web Access page? Wouldn't it be awesome if a user entered https://mail.contoso.com into their browser, and ended up with the Outlook Web Access? This can be achieved by creating a CNAME record that points to mail.office.com. Let's have our script create entries for mail and webmail perform this redirection.
Now back to the script.
This was a simple script, it doesn't have any complex logic, it will need the following information:
- CloudFlare API Token and email address; this is obvious as we need to talk to the CloudFlare Client API.
- The domain name.
- Do we want to create mail records? Lync records or both?
This is a very, very simple script, we just need to have a set of New-CFDNSRecord calls, with various controls depending on what we require.
For example, creating the MX record is as simple as:
This script only took an hour or so for testing and development time, however there was quite a bit of effort directed to changes in the Posh-CloudFlare and the New-CFDNSRecord CMDLet. If you look at the diff's between the last few versions, you will notice the following changes:
- The CMDLet now accepts input from the pipeline (in this case via property name).
- Restructure the CMDLet into Begin/Process/End (required for proper handling of pipeline input).
- Implementation of parameter sets.
- Cleanup of the validation of parameters.
I added parameter sets to New-CFDNSRecord with the aim to remove the somewhat faulty validation that I had previously. Whilst this sounded, and looked like it was simple, it actually took a few tried to ensure that the CMDLet would function appropriately. This was really interesting and deserves its own post in the future.
Parameter validation was updated in all of the CMDLets to improve email address validation. Previously, validation consisted of testing for an "@" character. Now I am using a regular expression.
Finally, I have spent some time cleaning up the code, not just within New-CFDNSRecord, but across all of the CMDLets. I have been trying, where possible to use ISE Steroids to ensure that everything I right is neat and presentable; it is a fantastic resource.
My final thought on all of this journey is, why couldn't Microsoft have implemented something like this? Microsoft has integrated the process with a bunch of other DNS providers, including the likes of GoDaddy, Network Solutions, 1 and 1 and even Yahoo Small Business. Why can't it also look at CloudFlare?
You can find the finished script over at GitHub, at Posh-Office365CloudFlare, the script is called Register-Office365.ps1. I have included comment based help with examples.
Kieran Jacobsen
Crossing the PowerShell streams
I was recently working with the PowerCat code which was capturing the Pipeline and Error output of code, and wondered, could I also capture the other messages being displayed? Why couldn’t I also redirect the warnings or the verbose output as well?
Let’s revisit how the redirection of the streams works in PowerShell, and hopefully learn about how PowerShell does things under the covers.
To explore the output streams, I am going to use the CMDLet I have below, which is a varation of the one June Blender used in her post on this topic.
It should also be noted that redirection to a variable is similar as to a file. In my examples I am redirecting to a variable.
So what happens if we run this CMDLet normally? We should see four distinct messages, first is out the text we are displaying by just returning a string, next we will have our write-output, then we have write-warning, and finally we will have the wrote-error message (and its associated trace).
What happens if we decide to assign the output to a variable called $output? Let’s take a look.
As you can see, after running the function, we still saw the warning and error messages. What was stored in the variable? Well if we look at that we can see that the text return and the write-output were successfully assigned to the variable $output.
Ok, so how about we apply the old redirection rules that have existed in every shell since the 80s?
Well this is much as we expected, but wait, the warning was displayed and not captured in the variable. The variable has our two output strings and it also has the write-error message as well. As a side note I love how the when calling $output PowerShell still displays the error in red.
If you are running PowerShell 2.0 (or less), this is the end of the line for you. There is no help for you.
If you are running PowerShell 3.0 (or greater), then how do we capture that warning message? What about the verbose?
With the introduction of PowerShell 3.0, Microsoft included support for capturing the other streams, and they did so in a method which is simple, clean and logical. Microsoft simply extended the stream redirection along the well-known and practiced methods.
Let’s take a look at the streams in PowerShell 3.0:
| Stream Number | Stream Description | Redirection |
|---|---|---|
| 1 | Pipeline/Output/Success | > |
| 2 | Error | 2>&1 |
| 3 | Warning | 3>&1 |
| 4 | Verbose | 4>&1 |
| 5 | Debug | 5>&1 |
| * | All | *>&1 |
Let’s take a look at the previous example again, however this time we will redirect the output of stream 3, warning, to stream 1.
As you can see, we captured this information just as expected.
Let’s try verbose output now.
We can see that simply using 4>&1 captures the output. We can also capture all output using the wildcard, *>&1.
I can hear one person asking, “But what about write-host?”
There are many reasons why you should not use write-host, firstly, Jeffrey Snover, the creator of PowerShell says not to, Don Jones, a PowerShell MVP says “Write-host kills puppies” <link>, however both agree, as does the PowerShell community, that there are some times when it might be handy to use Write-Host. Write-Host is black PowerShell magic, it’s the dark side of PowerShell. It is not something you should do without very thoroughly thinking about what you are about to do.
The only legitimate time to use Write-Host, is when you do not want to interrupt or pollute your stream. If you have a situation where you wish to display text to the user in such a way that it will not be caught up in the pipeline.
I only use Write-Host in one piece of code. I use it as part of my modular alerting framework, where I know that the message needs to be seen by the actual user of the code. I also didn’t want event/alert messages contaminating any of my other pieces of code. When I wrote the code, I knew it was a risky piece of code, however it has a clear cut function and purpose.
So what happens to Write-Host and redirected streams? To show you, I have added a Write-Host line to our previous CMDLet as show below:
Let’s run the code, redirecting all input (*>&1) into $output.
As you can see, the write-host was still displayed, everything else was captured in $output.
So what information is around on stream redirection? There are three good resources, firstly, check out June’s post on Hey Scripting Guy, secondly, PS> Get-Help about_Redirection and finally, there is the Microsoft Connect entry where the functionality was requested.
Kieran
PS. No streams were crossed during the creation of this post.
Hacking with a rubber duck
On the weekend I had the pleasure to present at CrikeyCon 2015. I want to thank everyone involved including the organizers; the other speakers; our wonderful MC, Patrick Gray from Risky Business; and of course the attendees!
This year I chose something a bit different to present on, the Hak5 Rubber Ducky. I started with two (and one failed,) demonstrations in the morning before setting up in the events area to show off some more advanced demonstrations.
As promised, I am posting up my content for everyone to make use of it.
Firstly, the PowerPoint slides can be downloaded here, or viewed on SlideShare here (and below).
I have setup a separate page on this side, Rubber Ducky, where you can find the scripts/payloads and a description with each.
There are a number of links which I found to be extremely useful.
If you have any questions, comments, or feedback please feel free to leave a comment, contact me via this site or send a message to me on Twitter.
Kieran