Skip to content
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 CVE-2020-0787 - Windows Background Intelligent Transfer Service (BITS) Elevation of Privilege Vulnerability #13554

Merged
merged 38 commits into from Jun 11, 2020

Conversation

gwillcox-r7
Copy link
Contributor

@gwillcox-r7 gwillcox-r7 commented Jun 3, 2020

This pull request adds support for exploiting CVE-2020-0787 on Windows 10 machines that users already have a Meterpreter session on. Successful exploitation leads to arbitrary code execution as SYSTEM. This exploit has been tested on Windows 10 v1909 x64 and x86 and has been confirmed to work successfully.

A couple of things to note here which are important if your testing this. Pay particular attention to points 1, 4, 5 and 6.

  1. The machine must be internet connected or BITS will not work. If you have network connectivity, but your in some restricted environment where you can't access the internet, then the BITS job that this exploit relies on will enter a suspended state whilst BITS waits for internet connectivity to occur again. This also means that if your testing in a VM, having it on anything but NAT will also cause the exploit to fail for similar reasons (aka you can't use the Internal Network adapter or similar). We may want to look into a solution for this but right now this hasn't been fixed.

  2. The exploit is not very good at cleaning up. I've added some notes but there appears to be a dangling handle issue in the Cleanup() method of the original exploit which means that the bait directory is only cleaned up after the spawned notepad.exe that we inject into is closed (which will happen when our elevated session is closed).

We also can't clean up the WindowsCoreDeviceInfo.dll file we drop at C:\Windows\System32\WindowsCoreDeviceInfo.dll as well since at the time of exploitation that will be being used by usocoreworker.exe, a process that is running as SYSTEM and which will have a handle to this file.

The work around for this right now is to migrate into another SYSTEM process, then find the PID of usocoreworker.exe, by using ps from within the elevated Meterpreter shell, kill that process, then run rm C:\Windows\System32\WindowsCoreDeviceInfo.dll from within the elevated Meterpreter shell.

You will also find that %TEMP%\workspace still exists as a folder after exploitation due to the dangling handle issue mentioned above causing the Cleanup() method of the DLL to fail due to notepad.exe having a handle to %TEMP\workspace\bait. You can verify this with Process Explorer if you want.

  1. Re-exploitation is possible, however it currently involves cleaning up the folders as mentioned above, killing the usocoreworker.exe process as mentioned above, and optionally removing C:\Windows\System32\WindowsCoreDeviceInfo.dll.

  2. This exploit will only grant a shell on Windows 10 at the moment. The reason for this is that whilst the arbitrary file copy exploit will work on any affected system, we need some method to leverage the arbitrary file copy to gain a system shell. The way we do this on Windows 10 is to leverage the Update Session Orchestrator service DLL hijacking technique, which is discussed at https://itm4n.github.io/usodllloader-part1/ and https://itm4n.github.io/usodllloader-part2/ for those who wish to know more. The nutshell version though is that the Update Session Orchestrator service was only introduced with Windows 10, so this technique doesn't work on anything prior to Windows 10.

If you have ideas for other universal privilege elevation methods which will work across a wide range of patches on Windows 8 or Windows 7, I would be very much interested in hearing them as I'd like to get this PR working on as many systems as possible.

  1. Currently there is a possibility that this exploit may cause the target PC to become incredibly slow to respond. I have experienced a lot of this prior to using Rapid7's build of the USODLL project, located at https://github.com/rapid7/metasploit-framework/tree/9769e04b6eecce4596335142a5ccc783b449038b/external/source/uso_trigger, but the issue may still be there as I have noticed occasional slow down for several minutes after exploitation. This is something I'd like to try investigate more to determine if it will be an issue or not and if so how to fix it.

  2. Currently this exploit has some popup messages triggered via MessageBoxA() that are in there for debugging purposes. I will remove these soon but they are in there to help people better debug where any errors are occuring.

With all that in mind, feel free to test this out and enjoy! Below are the verification steps:

Verification

List the steps needed to make sure this thing works

  • Start msfconsole
  • Get a Meterpreter session on the target machine
  • use exploit/windows/local/cve_2020_0787_bits_arbitrary_file_move
  • set SESSION *id of session you got on the target machine*
  • set PAYLOAD windows/meterpreter/bind_tcp if target is x86
  • set PAYLOAD windows/x64/meterpreter/bind_tcp if target is x64
  • set LPORT *some value that is not a port that the target is currently listening on*
  • set RHOST *target machine's IP*
  • Verify that the exploit runs and shows the output Sleeping for 30 seconds to allow the exploit to run...
  • Verify and click through all the popups that the DLL shows and that you see the popup with the message Setting things up succeeded!.
  • Verify the exploit sleeps for an appropriate amount of time and that this time isn't too long or too short to allow the BITS job to do its thing.
  • Verify you see Attempting to start the USO service to trigger the payload... being output and that there are no errors after this.
  • Verify you get a shell
  • Document anything that went wrong like timeouts, errors with the DLL, errors with the module, things you would like added, etc.

@gwillcox-r7 gwillcox-r7 marked this pull request as draft June 3, 2020 21:55
@gwillcox-r7 gwillcox-r7 added module needs-docs needs-linting The module needs additional work to pass our automated linting rules labels Jun 3, 2020
@label-actions
Copy link

label-actions bot commented Jun 3, 2020

Thanks for your pull request! Before this pull request can be merged, it must pass the checks of our automated linting tools.

We use Rubocop and msftidy to ensure the quality of our code. This can be ran from the root directory of Metasploit:

rubocop <directory or file>
tools/dev/msftidy.rb <directory or file>

You can automate most of these changes with the -a flag:

rubocop -a <directory or file>

Please update your branch after these have been made, and reach out if you have any problems.

@label-actions
Copy link

label-actions bot commented Jun 3, 2020

Thanks for your pull request! Before this can be merged, we need the following documentation for your module:

@gwillcox-r7 gwillcox-r7 self-assigned this Jun 3, 2020
@wvu wvu added the blocked Blocked by one or more additional tasks label Jun 3, 2020
@gwillcox-r7
Copy link
Contributor Author

Alright going to try look into the following today:

  1. Uploading the source code since I seem to have forgotten to do that.
  2. Adding in randomization to the folder names that are generated. Will require edits to the DLL. This should help prevent "match on this folder path name" AV signatures from picking this up.
  3. Add in checks to the exploit to better ensure that we are only targeting a Windows 10 machine, and not some other machine like Windows 8 or Windows 7 etc.
  4. See if the documentation needs updating to address the above point.
  5. Investigate if we still have any slowing down of the host and if so where its occurring. At the very least I'd like to try get this documented so I know in what instances its more likely to cause slowdown on the host.
  6. Add in option to Metasploit module to allow people to specify how long they would like to wait for the BITS job to complete before attempting to start the Update Session Orchestrator service to trigger the payload. Right now this is hardcoded in, we should really make this flexible.

Stretch goals but may be possible depending on time:

  1. Upload initial documentation for this exploit.
  2. Start investigating the main issue in all of this, the dangling handle reference 😨

@gwillcox-r7
Copy link
Contributor Author

gwillcox-r7 commented Jun 4, 2020

Well seems like there is a new issue now cause now when I reboot I can't get into my system and it just hangs on the login screen. This is for x64.

If I try the same thing with x86 and lock the PC whilst the exploit is running we will have similar effects as the login screen will spin forever after a successful login, but will never actually let the user log into the machine.

@gwillcox-r7
Copy link
Contributor Author

Alright going to try look into the following today:

  1. Uploading the source code since I seem to have forgotten to do that.
  2. Adding in randomization to the folder names that are generated. Will require edits to the DLL. This should help prevent "match on this folder path name" AV signatures from picking this up.
  3. Add in checks to the exploit to better ensure that we are only targeting a Windows 10 machine, and not some other machine like Windows 8 or Windows 7 etc.
  4. See if the documentation needs updating to address the above point.
  5. Investigate if we still have any slowing down of the host and if so where its occurring. At the very least I'd like to try get this documented so I know in what instances its more likely to cause slowdown on the host.
  6. Add in option to Metasploit module to allow people to specify how long they would like to wait for the BITS job to complete before attempting to start the Update Session Orchestrator service to trigger the payload. Right now this is hardcoded in, we should really make this flexible.

Stretch goals but may be possible depending on time:

  1. Upload initial documentation for this exploit.
  2. Start investigating the main issue in all of this, the dangling handle reference 😨

Steps 1, 3, and 6 of the main list above are now done, realized that documentation somehow got corrupted before I ever committed anything so need to go back and redo the module's output line for step 4 again. Hopefully once that is done we can look into trying to get step 2 done. Step 5 I think is related to that dangling reference issue so that may have to wait a bit.

Should also be able to get an initial draft of the documentation for this exploit put together and added to the docs/ folder.

@gwillcox-r7
Copy link
Contributor Author

gwillcox-r7 commented Jun 5, 2020

Alright managed to add randomization to the folder names that are generated and confirmed that is not impacting the exploit working. Also updated some of the module's output to be less misleading.

So essentially fixed step 2 and 4 of the main list above

@gwillcox-r7 gwillcox-r7 removed the needs-linting The module needs additional work to pass our automated linting rules label Jun 5, 2020
@gwillcox-r7
Copy link
Contributor Author

I don't know whats going on but now I'm getting it sometimes failing on the file check, and sometimes failing cause the BITS job is pointing to the right file but the handle is invalid. Basically some randomness is going on that wasn't happening before.

All of these issues started to happen right around the time that I added in the random file name generation code. I think it might be worthwhile to try go back to an earlier copy of my code, confirm that things are working on both x86 and x64, and then try work from there cause today has not gotten me anywhere beyond the addition of some documentation right now.

Hopefully then we can get the actual DLL code fixed up, and the rest of the module/documentation bits should remain as they are now with minor adjustments where needed.

@gwillcox-r7
Copy link
Contributor Author

Rolling back changes it looks like whatever I did with the folder name randomizer is to blame here, as if I go back to the commit before this was introduced, things seem to be fine again. Honestly the code was something I wasn't 100% sure about so this confirms I will likely need to take a closer look into it. For now though more concerned with getting this stable. AV evasion can wait until that is done.

@gwillcox-r7
Copy link
Contributor Author

Well originally I thought the issue was related to the lock screen/pressing CTL-ALT-DEL, but it seems that may not be the case. The issue still occurs after a few seconds (about 30 seconds to 70 seconds on average), and will lock up the entire PC. Better yet, you can't even shut it down normally, you have to literally power it and then power it back on again.

I mean its one method for persistence :D But yeah its not great.

In all seriousness though, the weird thing is that I left Task Manager up whilst I was doing this and CSRSS.exe and Desktop Manager seemed to be the last two processes that were running. Then we just enter a minimal to no CPU useage situation where no excess memory is being consumed, no excess CPU is being used, and I can't see anything that is using CPU at all; its like 2% CPU usage and no indication of a loop or similar being hit.

So yeah no idea which process is responsible for all this right now as even if I kill all my sessions and delete all the files, and kill the USO service, we are still out of luck.

I even tried waiting for a while to see if it would come back but nope it didn't. Talk about a bummer.

@gwillcox-r7
Copy link
Contributor Author

Hmm interesting. So this bug still triggers on a vanilla version of Windows 10 (original release aka Build 10240), however the Update Orchestrator technique doesn't work at all on that machine despite me reading through @itm4n's blog post and writeups. I'm not sure if something changed in the future: the service is definetely there, however running usoclient StartInteractiveScan doesn't start anything, and attempting to run UsoDLLLoader.exe results in Something went wrong (80070057 - "The parameter is incorrect")

@itm4n
Copy link

itm4n commented Jun 6, 2020

@gwillcox-r7 you're right. The Update Orchestrator trick no longer works on the latest WIP builds. It seems MS refactored the update process. As a result, the missing DLL is no longer loaded by the USO workers. I should add a note to my repo and blog post.

@gwillcox-r7
Copy link
Contributor Author

@gwillcox-r7 you're right. The Update Orchestrator trick no longer works on the latest WIP builds. It seems MS refactored the update process. As a result, the missing DLL is no longer loaded by the USO workers. I should add a note to my repo and blog post.

Thanks, appreciate the heads up 👍 Do you happen to know the range of non-WIP builds which this method affects? I thought it affected all Windows 10 builds up to and including v2004, but it sounds like Windows 10 TH1 (aka v1507) isn't affected given my current tests so trying to narrow down the field some more.

@wvu wvu added termux Used when an issue is related to Termux potato The issue submitter failed to update the default issue template or the issue is a literal potato and removed termux Used when an issue is related to Termux potato The issue submitter failed to update the default issue template or the issue is a literal potato labels Jun 7, 2020
@gwillcox-r7
Copy link
Contributor Author

gwillcox-r7 commented Jun 7, 2020

Hmm curious so its possible there is a lot of rundll32.exe processes that are being spawned which is causing the delay. Though I don't know if this was from previous attempts:

Lots of rundll32 processes

I have noticed that adding a ExitProcess() call into the program within the DllMain() function does help clean up things after we finish executing exploit() and ensures we kill off the dangling NotePad.exe process. So will probably keep that in final exploit but playing around with a few ideas right now.

For the moment it seems like FindBitsTempFile() may be where the dangling handle occurs based on some initial debug message tests I ran, but not confirmed 100% yet.

@gwillcox-r7
Copy link
Contributor Author

Ok further testing is confirming that for some reason the file handle that is created in FindBitsTempFile() is not being closed correctly, as within that function the handle should be created by a call to FindFirstFile() which will then be closed by CloseHandle(). Looks like I will need to do further investigation to figure out why it can't close this handle as according to Process Explorer the handle doesn't exist before this call, despite me placing a 30 second wait after the PrepareJob() call to ensure its not PrepareJob()'s fault.

@gwillcox-r7
Copy link
Contributor Author

Ah well thats a classic :D Appears from reading the MSDN documentation on FindFirstFile() that you are meant to close the handle with FindClose(), not via CloseHandle(). Let me see if this fixes things. If it does this would explain a lot :P

@gwillcox-r7
Copy link
Contributor Author

gwillcox-r7 commented Jun 7, 2020

Woot woot! That seems to have solved it. @itm4n you just need to change the line in BitsArbitraryFileMove::FindBitsTempFile() from CloseHandle(hRes); to FindClose(hRes);

Update: Logged an issue at https://github.com/itm4n/BitsArbitraryFileMove/issues/3 just so its logged in a better location. Should be a simple fix by changing the line as mentioned above.

@gwillcox-r7
Copy link
Contributor Author

Okay so think I can explain the other issue that is occurring here, and this one is a little tricker. It seems like usocoreworker.exe may occasionally spawn multiple instances of rundll32.exe on a target, which can lead to 100% CPU useage.

This can be seen if we lock the PC whilst running the exploit. Here is what it looks like before the exploit starts:

before

And directly afterwards:

after running the LPE

And here is after we lock the PC whilst the SYSTEM shell we have obtained was opened. Notice the abundance of run32.dll and that this was tested on a x86 system:

rundll32 exe spawning multiple times after locking whilst running shell before it eventually takes over

A further inspection reveals these were all created by usocoreworker.exe:

seems like these are being repeatively spawned by usocoreworker-exe

This can then be observed to spike the CPU usage up to 100%:

note that cpu useage is now at 99 99 percent

@gwillcox-r7
Copy link
Contributor Author

Also here is some further confirmation that this is what is causing the hangs (taken after trying to run an elevated process):

hang cause of rundll32 consuming CPU resources

@gwillcox-r7
Copy link
Contributor Author

@wvu-r7 sorry for the odd change, I rebased this ontop of the latest changes to the master branch. Latest commits (should be last 3) add in:

  1. Link to my AttackerKB assessment in references.
  2. Updates to the DLL template generation files so that it will generate them with the correct name and place them in the right location (I hope its the right directory).
  3. Updates to documentation to reflect recent changes to the output.

@wvu wvu changed the title Add CVE-2020-0787 - Windows Background Intelligent Transfer Service Elevation of Privilege Vulnerability Add CVE-2020-0787 - Windows Background Intelligent Transfer Service (BITS) Elevation of Privilege Vulnerability Jun 10, 2020
@wvu wvu added the needs-linting The module needs additional work to pass our automated linting rules label Jun 11, 2020
@label-actions
Copy link

label-actions bot commented Jun 11, 2020

Thanks for your pull request! Before this pull request can be merged, it must pass the checks of our automated linting tools.

We use Rubocop and msftidy to ensure the quality of our code. This can be ran from the root directory of Metasploit:

rubocop <directory or file>
tools/dev/msftidy.rb <directory or file>

You can automate most of these changes with the -a flag:

rubocop -a <directory or file>

Please update your branch after these have been made, and reach out if you have any problems.

@wvu wvu removed the needs-linting The module needs additional work to pass our automated linting rules label Jun 11, 2020
wvu added a commit that referenced this pull request Jun 11, 2020
@wvu wvu merged commit 1e7e346 into rapid7:master Jun 11, 2020
@wvu
Copy link
Contributor

wvu commented Jun 11, 2020

Release Notes

This adds a local exploit for CVE-2020-0787, an elevation of privilege vulnerability in the Windows Background Intelligent Transfer Service (BITS).

@gwillcox-r7 gwillcox-r7 deleted the CVE-2020-0787 branch June 11, 2020 06:14
'License' => MSF_LICENSE,
'Author' =>
[
'itm4n', # PoC
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gwillcox-r7: I think @itm4n discovered this as well.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep he did, want me to update the comment on this to reflect that?

Comment on lines +34 to +35
6. Do: ```run```
7. You should get a shell running as SYSTEM a few seconds after the `JOB_WAIT_TIME` timer expires.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

7 8

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

67678678687678969698769786978

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

63616e20776520737469636b20746f20617363696920706c65617365204920646f6e277420737065616b206d75636820686578

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

4 8 15 16 23 42

@tperry-r7 tperry-r7 added the rn-modules release notes for new or majorly enhanced modules label Jun 25, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs module rn-modules release notes for new or majorly enhanced modules
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants