Print Spooler EoP – CVE-2020-17001
A few months ago, as part of our Black Hat 2020 USA talk – “A Decade After Stuxnet’s Printer Vulnerability, Printing is still the Stairway to Heaven”, we introduced two Elevation of Privilege vulnerabilities which we found within the Windows Print Spooler mechanism.
Today, we will introduce the patch of the CVE-2020-170071 vulnerability which, allegedly, is supposed to mitigate further bugs in this area of the Print Spooler mechanism.
1st Vuln – CVE-2020-1048
The Print Spooler mechanism provided the option to print (write) arbitrary data to a file. We found that this feature can be abused in order to write arbitrary data to any file on behalf of NT AUTHORITY\SYSTEM, resulting in Local Privilege Escalation and Code Execution.
The root cause was pretty simple:
- A limited user could’ve crafted a print job (an SHD file) which contains arbitrary data and an arbitrary file path.
- Once the Print Spooler service was being initialized, it processed and printed the previous unprocessed print jobs, while running as NT AUTHORITY\SYSTEM, without being aware of which user created the print job. 3.Last but not least, the arbitrary data was written to the arbitrary path by the Spooler service as NT AUTHORITY\SYSTEM.
2nd Vuln – CVE-2020-1337
After the CVE-2020-1048 vulnerability was patched, we found a way to bypass the patch.
The patch has prevented a limited user from printing data to a directory (printer port) which he doesn’t have write access to. The problem was that the restriction was applied only during the time that the user specified the file path of the printer port, but not during the printing process itself.
This time, as you probably guessed, it was a TOCTOU bug which we were able to exploit. We have specified a dummy directory as a limited user, which we had permissions to write to. After we passed the validation, we removed the dummy directory and redirected it to System32 by using an NTFS Mount Point.
The CVE-2020-1337 patch has solved the original problem by:
- calling the GetFinalPathNameByHandle function which, in our case, retrieves the path which the symbolic link points to.
- Validating that the printing user has write permissions to the final path.
3rd (Last?) Vuln – CVE-2020-17001
This Spooler EoP vulnerability was found by James Forshaw of Google Project Zero and was patched by Microsoft in the recent Patch Tuesday. I will explain the bug in a brief, for a deep analysis, please check the Project Zero website.
It mitigated our bypass, but apparently, James Forshaw has found another bypass.
The exploitation of CVE-2020-17001 is very similar to the previous exploits, but instead of using a regular NTFS Mount Point or a Junction, a UNC path is being used.
These are the exploitation phases:
- Creating a dummy folder (e.g. c:\temp)
- Adding a printer and a printer port which points to UNC path the dummy folder (e.g. \localhost\c\$\temp)
- Deleting the dummy folder and overwriting it with a Junction which points to System32. 4.The GetFinalPathNameByHandle function will try to retrieve the final path of the UNC path, but won’t be able to, so it will return the UNC path which the user has write permissions to, which means the exploitation will be successful.
The 3rd and probably final fix for the never ending bug
You have probably noticed that the actual root cause for the 3 vulnerabilities we have presented is the fact that the Print Spooler processes and prints the previous print jobs as NT AUTHORITY\SYSTEM, without being aware of who created the print job.
It appears that the patch of CVE-2020-17001 which was delivered in the recent Patch Tuesday has finally fixed the problem (we hope :D.)
Microsoft has added a function named IsSpoolerImpersonating, which is called during the printing process to a local port (which might be a file.)
The function tests the SID of the current thread, and validates whether it’s running under the context of LocalSystem. If the first one is true, the printing process is canceled, mitigating all of the 3 vulnerabilities we have shown today.