by Mitja Kolsek, the 0patch Team
Nine days ago we issued micropatches for a vulnerability that allows attackers to bypass the warning Windows normally present to users when they try to open a document or executable obtained from an untrusted source (Internet, email, USB key, network drive). That vulnerability, affecting all supported and many legacy Windows versions, still has no official patch from Microsoft so our (free!) patches are the only actual patches in existence as of this writing.
On the very same day we issued these micropatches, Will Dormann - who researched said vulnerability - replied to a tweet by another security researcher, Patrick Schläpfer. Patrick works at HP Wolf Security where they analyzed the Magniber Ransomware and wrote a detailed analysis of its working. Will asked Patrick about the ZIP files used in the malware campaign to see if they were exploiting the same vulnerability or employing some other trick to bypass the "Mark of the Web".
Patrick responded that malicious files extracted from the attacker's ZIP files did have the Mark of the Web but still executed without a security warning. Remember that on Windows 10 and Windows 11, opening any potentially harmful file triggers a SmartScreen inspection of said file, whereby SmartScreen determines if the file is clear to get launched or the user should be warned about it (see image below).
|SmartScreen determined that this file could be harmful and warned the user. The user needs to click "More Info" and then press "Run" if they really want to open the file.|
When deciding whether to trust the file or not, the Mark of the Web plays an important role: files with this mark are considered unconditionally untrusted as they originated from an untrusted source. So why did these malicious Magniber files not trigger the SmartScreen warning?
Patrick remarked that Authenticode signatures on extracted malicious files must have been causing this behavior because with signatures removed, the warning would (correctly) appear.
Will then noticed that these signatures were not valid at all and should not have been trusted by Windows. In fact, they were malformed such that Windows could not even properly parse them. This, for some peculiar reason, led to Windows trusting them - and letting malicious executables execute without a warning.
And so a new 0day - already exploited in the wild - was revealed.
This information was sufficient for us to start our patch development process. We reproduced the issue using a sample .JS file with various malformed signatures until we reached the flawed execution path that bypassed the SmartScreen warning. We then searched for the cause, and found... well... it's complicated.
The logic behind determining whether to show a security warning to the user, and whether to show the SmartScreen warning or the old "Open File - Security Warning" dialog, is complex and distributed among various executable modules. An application attempting to open a file on user's behalf partly inspects the file itself to decide whether to send it to further inspection by SmartScreen, and if so, sends a DCOM request to SmartScreen.exe, which is another process constantly running on Windows. SmartScreen.exe then does its own inspection and, if networking is available, asks Microsoft's servers for an opinion, displays the warning if needed, then delivers the final verdict back to the requesting process in form of an error code and the information on user's decision ("Run" or "Don't run").
What looked like the most serious flaw to us was the fact that when SmartScreen.exe returns an error, this would be considered identical to the user having pressed "Run." A strange decision, security-wise.
The malformed signature discovered by Patrick and Will caused SmartScreen.exe to throw an exception when the signature could not be parsed, resulting in SmartScreen returning an error. Which we now know means "Run."
Mystery solved. Now let's patch it.
To understand our patch, we need to take a closer look at function DoSafeOpenPromptForShellExec in shdocvw.dll as this is the function that performs the flawed logic. The image below shows the relevant part of its code: register edi is initialized to 0 and is reserved for holding the final decision on whether to run/open the file or not. The function sends a request to SmartScreen and waits for its response, then based on the error code returned takes the left or the right branch. The right branch, executed when there was no error, stores the user's decision to edi; the left branch, executed when SmartScreen returned an error, leaves edi on 0 - which explains why an error equals the user's decision to run/open the file.
The simplest way to fix this would be to simply initialize edi to a value that would mean "Don't run", whereby any error in SmartScreen would lead to the file not being run/opened. However, this approach might confuse users as such files would just silently not run/open without any feedback to the user.
We therefore decided on a different approach: in the same function, there is a code block that displays the old "Open File - Security Warning" dialog to the user, and in case of a SmartScreen error, we redirect execution to that block. This way, when SmartScreen errors out, the user is presented with the old security warning and can still select whether to run/open the file or not.
While our patch fixes the most obvious flaw, its utility depends on the application opening the file using function DoSafeOpenPromptForShellExec in shdocvw.dll and not some other mechanism. We're not aware of another such mechanism in Windows, but it could technically exist. Our tests with opening files directly from Windows Explorer, from ZIP files opened with Windows Explorer, and directly from most major web browsers and email clients were successful. Except with Google Chrome, which we've long ago decided not to patch because its sandboxing model is causing us problems with injection. And even if we did patch Chrome, there is another weird logic in shdocvw.dll that gets executed in Chrome due to sandboxing which for some reason prevents SmartScreen from returning an error while still not showing the warning. We did not investigate the latter any further.
We did, however, investigate a possibility of patching SmartScreen.exe, which could potentially cover all cases, but that would have to be a much more complex patch. In addition, the SmartScreen code can throw an exception in numerous places in addition to the one triggered by a malformed signature, and each of these could lead to the same warning bypass.
Needless to say, we're very interested in learning how Microsoft will fix this issue. Meanwhile though, our patch probably covers the majority of attack scenarios.
Our Micropatch In Action
You can see the effect of our micropatch in the following video. There are two executable files on the desktop: goodsig.exe and badsig.exe. Both are really just calc.exe and both have the Mark of the Web, but the former has a proper parsable signature while the latter has a malformed, unparsable signature that causes SmartScreen to error out.
Without our micropatch, double-clicking goodsig.exe correctly shows the SmartScreen warning because any executable with Mark of the Web should trigger the warning. Double-clicking badsig.exe, on the other hand, just launches the executable without any warning - demonstrating the vulnerability.
With 0patch enabled and our micropatch applied, double-clicking goodsig.exe behaves the same as before (which is still correct), but double-clicking badsig.exe now triggers the "Open File - Security Warning" dialog, warning the user and allowing them to back out via the "Cancel" button.
this is a "0day" vulnerability with no official vendor fix available,
we are providing our micropatches for free until such fix becomes
Micropatches were written for:
- Windows 11 v21H2
- Windows 10 v21H2
- Windows 10 v21H1
- Windows 10 v20H2
- Windows 10 v2004
- Windows 10 v1909
- Windows 10 v1903
- Windows 10 v1809
- Windows 10 v1803
- Windows Server 2022
- Windows Server 2019
Note that Windows 7 is not affected by this issue, neither are Windows Server 2008 and 2012.
These micropatches have already been distributed to all online 0patch Agents. If you're new to 0patch, create a free account in 0patch Central, then install and register 0patch Agent from 0patch.com. Everything else will happen automatically. No computer reboot will be needed.
We'd like to thank Patrick Schläpfer for sharing the details on their Magniber ransomware analysis and Will Dormann for their analysis of this vulnerability that allowed us to reproduce it and create a micropatch. We also encourage security researchers to privately share their analyses with us for micropatching.