Our Vulnerability is an elevation of privileges in the windows installer, let’s browse through windows folders, there is a hidden folder(“C:\Windows\Installer”) it contains some already installed packages *.msi, they are always available there since drivers installation use msi packages . from where do the files come? When an installation is done, windows installer copies, then create an msi file to our packages folder for some uninstallation or repair stuff ... but the most interesting part is the repairing part, a standard unprivileged user could repair some packages. Returning to the old known vulnerability CVE-2019-1415 -> https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2019-1415. This is a bypass for the security patch, it says that the windows installer improperly handling file operation and after some searching, I found something interesting, so what's the interesting part, the interesting part is the acknowledged girl is Polar Bear. A.K.A “Sandbox Escaper”. Let`s see exploit-db and here is the exploit https://www.exploit-db.com/exploits/46916 . after browsing, it just looked like windows installer is not correctly handling the junctions so let’s test the bug on a patched machine, the result is just the installer will look for any existing folder or links and delete them if it fails
If you took a look in the sandboxescaper’s poc , she said that the installer when executed with repair flag it would trigger the rollback as system but how as a standard user ... by default in a fresh windows installation there’s a service called windows installer which run as SYSTEM privileges , by default when launching a package with repair flag the installer run 2 time , one as the current user and another as a service running as system , the one who is running as a standard user is for user interaction but the system service run to repair and modify package content which is located generically in "C:\Program Files" we are trying to abuse the system one . the system windows installer create a folder in c:\ called Config.Msi , and it put some rollback file (*.rbs or *.rbf) .
At the beginning I throught it should be very easy but it’s harder than I think especially in the poc part , really there is still a bug in the installer . Microsoft didn’t patched the issue they
just make the race harder to win ... let’s take a short view to the outdated version , you can use process monitor it’s available here => https://docs.microsoft.com/en-us/sysinternals/downloads/procmon, to monitor all the installer file operation .
So let’s see the outdated version of the installer
so it’s look very easy to fool using reparse point (also know as directory junction) , so lets take another look on the patched one
I highlighted the important operation which are SetSecurityFile and QueryNetworkOpenInformation , so setsecurityfile is clear but the thing that need explanation is the QueryNetworkOpenInformation , so generically this function just look like GetFileAttribute
So GetFileAttribute is a function give the caller some information about a folder or a file , I did a test when I plant a Junction before the call of the function and after the call of the function , the installer either will crash or give a message “C:\Config.Msi is not available” okay so ... what if we planted a junction after the check . the answer simply is a failure there’s multiple checks so abusing directory with links is made impossible , its still possible with an incredible hard to win race so definitely you will some 16 core cpu to win the race and combined with some luck you will got the original poc to work again . but let’s think about that we don’t need any performance its something depending on your luck and I know my luck I will never get a triggered bug L so I should work smarter . links are not the ideal solution I I thought about this after one week of thinking sooooo always there is another way let’s take another look in procmon , the setsecurityfile can be easily bypassed with no need to use junction -this is the first race- if we handle the folder after the creation and before the SetSecurityFile so something like this should but there’is a problem in the latest patch the installer is putting some temporary files in C:\Config.Msi \*.tmp
Look at the highlighted one , before doing any file operation the installer is doing a check first to make sure there is no already created folder or junction after doing the check it put a temp file there , I still doesnt know for what purpose is it but look like a check to make sure the directory is write able I THINK AM NOT SURE, but after putting the file there it just query some information and then simply delete it and delete the c:\config.msi ...
But this is not the important part we don’t need to care , may this can be abused for an arbitrary file creation I didn’t do any test because it’s not our target , our target is the rollback files after that the installer is checking again for any available folders with name Config.Msi if a folder the installer will raise an error otherwise if nothing found it would create a new one
After the creation is successful the installer will call setsecurityfile with a security descriptor preventing a standard user from reading or writing
So our race is to try to handle the folder using CreateFile() function and yup the function is returning a valid handle to the directory which can be used in multiple operation so something like that will do the job :
NOTE : this is not the final poc so don’t expect this code with the attached code.
However after running the polarbear in several time we will got a good result:
The poc got the access to the C:\Config.Msi folder we got a security descriptor which do no prevent a standard user from modifying the directory so how ?..
If you noticed the specified flag in CreateFile “FILE_FLAG_DELETE_ON_CLOSE” the specified flag is saying (“if the handle is closed the automatically delete the folder”) so it return success if we called the function before the SetSecurityFile() function so what do after deleting the directory , simply recreate another one with CreateDirectoryW(L"C:\\Config.Msi", NULL); which make the directory write able again . (Cause of the default inherit permission from “C:\”) .
Let’s say accessing to the protected folder C:\Config.Msi is already an elevated permission because we hijack files. The *.rbf are Roll Back Files when the installer is repairing a package it could copy a file to the C:\Config.Msi\*.rbs to use it later if a rollback triggered
A simple example there , the installer is copying the file “stop-listener.bat” to C:\Config.Msi (that what SetRenameInfoByHandle() do.) simply we can write to the file something and trigger the rollback and then the “stop-listener.bat” will be moved to its original place , and simply we got system privileges , AM NOT SURE . But this is not very important to us cause it’s not abuse-able from all cases so let’s go back to the rbs files.
So we need to get into the hardest race, the race which give us the access to the rbs file let’s take another look at procmon:
After looking at this more than a day , the installer made the abusement of the operations using the junction an impossible thing so let’s think again the installer is looking for junction before it write the file and after writing it , possible abusement if put a reparse point after the check and before the check we will get what we are there for but it’s impossible to get that result . We can’t delete the file since the installer is specifying an ACL which prevent the user from opening the file for reading, writing or deleting. But the installer is only checking for reparse point let’s say it’s still vulnerable ... since we can’t delete the folder there’s another way we can still rename it since the renaming is not requiring any access to the file inside the directory there’s still an abusement to gain the SYSTEM privileges .
The last patch leaved a hole which we can use it to gain the access to the rbs file , after the installer is creating the config folder it call SetSecurityFile to prevent users from accessing to the config folder and the it check if there’s a reparse point and then create the file *.rbs , close it and check again if there’s a link . The security hole is when the installer is closing the file it leave the rbs file to the attacker , after the file is closed the attacker will rename the folder and create new one and then create a new rbs file which is dangerous and it’s and the attacker can gain system privileges by modifying files . Our biggest problem is how to trigger the rollback in the installer , sandboxescaper mentioned that you will need to inject something to the installer which it would some hard work to hook the entries and since I have 5 tests tomorrow am not sure I have time to do that . after I read the Microsoft documentation about the installer https://docs.microsoft.com/en-us/windows/win32/msi/rollback-installation. The document said that installer will trigger to rollback automatically if something is wrong , I started missing with the process and just I killed installer and surprise the installer is triggering the rollback without any user interaction . after running the poc we will get something like this:
And the result is:
It’s very hard to win the race and even impossible you will need something that load cpu hugely , for me running chrome 15 time is enough to win the race . I’ve provided the asus atk package for testing purpose , make sure to install it as an administrator . and when you run the poc you will need to run the installer with the repair flag like that
And about finding package it’s easy the size is about 11.487KB so find it .
I don’t know if the issue will trigger on your own machine or no , I’ve attached a case of a successful exploitation for review you might need procmon to open the file.
That wasn't a funny exploit, it took from me 1 month to write the poc, but the bright side Microsoft Has rewarded me the maximum bounty. As you can see
Thank You For Reading, and happy hacking !