by Mitja Kolsek, the 0patch Team
Last Friday, Microsoft published an advisory about a remotely exploitable memory corruption vulnerability (CVE-2020-0674) that was reported to them by Qihoo 360 as being exploited in the wild. These attacks were reportedly limited so Microsoft decided not to rush with issuing a patch but will rather provide one as part of February's Patch Tuesday. They did, however, provide a workaround.
Because the provided workaround has multiple negative side effects, and because it is likely that Windows 7 and Windows Server 2008 R2 users without Extended Security Updates will not get the patch at all (their support ended this month), we decided to provide a micropatch that simulates the workaround without its negative side effects.
The vulnerability is in jscript.dll, which is the scripting engine for legacy JScript code; note that all "non-legacy" JScript code (whatever that might be), and all JavaScript code gets executed by the newer scripting engine implemented in jscript9.dll.
Microsoft's workaround comprises setting permissions on jscript.dll such that nobody will be able to read it. This workaround has an expected negative side effect that if you're using a web application that employs legacy JScript (and can as such only be used with Internet Explorer), this application will no longer work in your browser.
There also several other negative side effects:
- Windows Media Player is reported to break on playing MP4 files.
- The sfc (Resource Checker), a tool that scans the integrity of all protected system files and replaces incorrect versions with correct Microsoft versions, chokes on jscript.dll with altered permissions.
- Printing to "Microsoft Print to PDF" is reported to break.
- Proxy automatic configuration scripts (PAC scripts) may not work.
Microsoft's advisory states that the provided workaround will have to be reverted when they issue a patch for jscript.dll. However, note that some additional side effects may result from changing the ownership on jscript.dll (from TrustedInstaller to the user you're implementing the workaround as).
Test Case
Finding a test case that triggers the loading of jscript.dll was not difficult - Google Project Zero has one published in an advisory from November last year. (It won't be at all surprising if the vulnerability at hand is either a clone of that one, or a bypass for its patch - but we'll know soon enough.)
So we took Google's example, simplified it to only cause the loading of jscript.dll for executing a single alert call. Note the important part is to specify JScript.Encode as language. (By the way, read the Wikipedia article on JScript.Encode for a primer on how to underestimate intelligent adversaries.)
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=8"></meta>
</head>
<body>
<script language="Jscript.Encode">
alert("jscript.dll was loaded");
</script>
</body>
</html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=8"></meta>
</head>
<body>
<script language="Jscript.Encode">
alert("jscript.dll was loaded");
</script>
</body>
</html>
The test was then simple: opening this file in IE without mitigation or patch should result in a popup saying "jscript.dll was loaded". With a patch, we would want the loading of jscript.dll to fail and consequently no popup to appear. Ideally, in a graceful manner without any ugly error messages or crashed processes.
Analysis
Sabotaging some functionality is usually a simple thing to do with a micropatch: you locate the code that implements or initializes said functionality, and make it fail. This was a case here too.
We first used Process Monitor to locate the code in Internet Explorer which loads jscript.dll. This was trivial as Process Monitor records a call stack for every operation, and it was obvious that mshtml.dll causes the loading of jscript.dll through a call to CoCreateInstance.
lea eax,[esp+3Ch]
xor edi,edi
push eax
push offset MSHTML!_GUID_bb1a2ae1_a4f9_11cf_8f20_00805f2cd064 (631bf2a8)
push 1
push edi
lea eax,[esp+0B4h]
push eax
call dword ptr [MSHTML!_imp__CoCreateInstance (641c301c)]
mov ebx,eax
test ebx,ebx
xor edi,edi
push eax
push offset MSHTML!_GUID_bb1a2ae1_a4f9_11cf_8f20_00805f2cd064 (631bf2a8)
push 1
push edi
lea eax,[esp+0B4h]
push eax
call dword ptr [MSHTML!_imp__CoCreateInstance (641c301c)]
mov ebx,eax
test ebx,ebx
When this code is reached as a result of rendering a Jscript.Encode script block, the first argument (the last one pushed to the stack) points to a ClassID f414c262-6ac0-11cf-b6d1-00aa00bbbb58, which instantiates a jscript.dll object.
Great, could we just sabotage this call and be done with it? Unfortunately not; this same function is being used for instantiating other objects as well, so we need to be selective here.
We decided to make a micropatch that checks, before the call to CoCreateInstance is made, whether its first argument equals f414c262-6ac0-11cf-b6d1-00aa00bbbb58, and if so, sabotages the call by setting its last argument (pvv) to NULL, causing CoCreateInstance to return error 0x80070057 (E_INVALIDARG). This has the same effect as making jscript.dll impossible to read.
But before settling with that, we wanted to check if there were any other ways in which a malicious web page could have code executed by jscript.dll. So we scanned the Registry for all ClassIDs associated with jscript.dll that were loadable via a script tag - and found Jscript.Compact to be such an alternative. So we made another HTML test file:
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=8"></meta>
</head>
<body>
<script language="Jscript.Compact">
alert("jscript.dll was loaded");
</script>
</body>
</html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=8"></meta>
</head>
<body>
<script language="Jscript.Compact">
alert("jscript.dll was loaded");
</script>
</body>
</html>
And sure enough, this one also executed the alert with jscript.dll.We therefore had to add another ClassID check to our micropatch, also preventing cc5bbec3-db4a-4bed-828d-08d78ee3e1ed from getting instantiated.
The final micropatch then became:
MODULE_PATH "..\Affected_Modules\mshtml.dll_11.0.17763.831_32bit\mshtml.dll"
PATCH_ID 1000004
PATCH_FORMAT_VER 2
VULN_ID 5897
PLATFORM win32
patchlet_start
PATCHLET_ID 1
PATCHLET_TYPE 2
PATCHLET_OFFSET 0x3bcf36
N_ORIGINALBYTES 5
code_start
; At this point, ClassID is stored at address pointed to by [esp+0ACh]
; If we want to sabotage the call, we put 0 at [esp+0ch] (argument ppv), which
; will cause error 0x80070057 (E_INVALIDARG)
; Compare ClassID with f414c262-6ac0-11cf-b6d1-00aa00bbbb58 (Jscript.Encode)
cmp dword [esp + 0ACh], 0xf414c262
jne skip1
cmp dword [esp + 0ACh + 4h], 0x11cf6ac0
jne skip1
cmp dword [esp + 0ACh + 8h], 0xaa00d1b6
jne skip1
cmp dword [esp + 0ACh + 0Ch], 0x58bbbb00
jne skip1
mov dword [esp + 0xc], 0 ; Sabotage the call to CoCreateInstance by setting ppv to 0
skip1:
; Compare ClassID with cc5bbec3-db4a-4bed-828d-08d78ee3e1ed (Jscript.Compact)
cmp dword [esp + 0ACh], 0xcc5bbec3
jne skip2
cmp dword [esp + 0ACh + 4h], 0x4beddb4a
jne skip2
cmp dword [esp + 0ACh + 8h], 0xd7088d82
jne skip2
cmp dword [esp + 0ACh + 0Ch], 0xede1e38e
jne skip2
mov dword [esp + 0xc], 0 ; Sabotage the call to CoCreateInstance by setting ppv to 0
skip2:
code_end
patchlet_end
PATCH_ID 1000004
PATCH_FORMAT_VER 2
VULN_ID 5897
PLATFORM win32
patchlet_start
PATCHLET_ID 1
PATCHLET_TYPE 2
PATCHLET_OFFSET 0x3bcf36
N_ORIGINALBYTES 5
code_start
; At this point, ClassID is stored at address pointed to by [esp+0ACh]
; If we want to sabotage the call, we put 0 at [esp+0ch] (argument ppv), which
; will cause error 0x80070057 (E_INVALIDARG)
; Compare ClassID with f414c262-6ac0-11cf-b6d1-00aa00bbbb58 (Jscript.Encode)
cmp dword [esp + 0ACh], 0xf414c262
jne skip1
cmp dword [esp + 0ACh + 4h], 0x11cf6ac0
jne skip1
cmp dword [esp + 0ACh + 8h], 0xaa00d1b6
jne skip1
cmp dword [esp + 0ACh + 0Ch], 0x58bbbb00
jne skip1
mov dword [esp + 0xc], 0 ; Sabotage the call to CoCreateInstance by setting ppv to 0
skip1:
; Compare ClassID with cc5bbec3-db4a-4bed-828d-08d78ee3e1ed (Jscript.Compact)
cmp dword [esp + 0ACh], 0xcc5bbec3
jne skip2
cmp dword [esp + 0ACh + 4h], 0x4beddb4a
jne skip2
cmp dword [esp + 0ACh + 8h], 0xd7088d82
jne skip2
cmp dword [esp + 0ACh + 0Ch], 0xede1e38e
jne skip2
mov dword [esp + 0xc], 0 ; Sabotage the call to CoCreateInstance by setting ppv to 0
skip2:
code_end
patchlet_end
We ported this micropatch to the following platforms, both 32-bit and 64-bit:
- Windows 7,
- Windows 10 v1709,
- Windows 10 v1803,
- Windows 10 v1809,
- Windows 10 v1903, [issued on 1/30/2020]
- Windows 10 v1909, [issued on 1/30/2020]
- Windows Server 2008 R2,
- Windows Server 2019
If you're a 0patch user, you already have this micropatch downloaded to all your online computers with 0patch Agent, and - depending on your settings - already automatically applied to all processes using the Internet Explorer 11 engine for rendering content. This includes Internet Explorer (obviously), Microsoft Word, Microsoft Outlook, and a variety of other applications.
As all our micropatches, you can switch this micropatch on or off and have it instantly applied to, or removed from running applications - effectively making it a "kill switch" for jscript.dll.
If you're using other Windows versions or older Internet Explorer versions and are interested in having this micropatch ported to your systems, please contact us at sales@0patch.com.
Video
Here's our micropatch in action:
Frequently Asked Questions
Q: Why would we apply your micropatch instead of Microsoft's recommended workaround?
Our micropatch is designed to avoid negative side effects of Microsoft's workaround (see above). It can also be easily reverted (un-applied) with a switch of a button without leaving any traces, while the workaround changes the ownership on jscript.dll.
Q: Will Microsoft provide a patch for CVE-2020-0674 to Windows 7 and Windows Server 2008 R2 users without Extended Security Updates?
We don't know but these systems are now officially out of support and Microsoft has historically only issued security patches for unsupported systems in extreme cases (e.g., the Shadow Brokers leak, or BlueKeep / CVE-2019-0708).
We at 0patch have committed to provide post-end-of-service security micropatches for Windows 7 and Windows Server 2008 R2 for three additional years, which is why we're also issuing this micropatch for these platforms. (Read FAQ for more information.)
Q: What will happen if I apply your micropatch, and then apply Microsoft's patch for CVE-2020-0674 when it comes out?
When Microsoft issues a patch for this vulnerability, we'll inspect it and decide whether to replace our current micropatch (which resides in mshtml.dll and disables jscript.dll entirely) with a more targeted micropatch in jscript.dll (which will only fix that vulnerability but keep jscript.dll available). It might happen that we do so on supported Windows platforms but keep the current micropatch on Windows 7 and Windows Server 2008 R2. This also depends on user feedback (i.e., whether our micropatch causes anyone problems).
In any case, you won't have to do anything - Microsoft's patch will have precedence over our micropatch.
Q: I suspect your micropatch is causing problems on my computer. What should I do?
Make a quick test: Disable 0patch Agent and execute your affected process - if the problem is still there, it's unlikely the cause of your problem is our micropatch. However, if your problem goes away, please report that to support@0patch.com and temporarily disable micropatches 402-405 on your 0patch Agent.
Users on the Enterprise plan can enable and disable individual patches centrally through 0patch Central.
Q: Are there any applications using jscript.dll directly (not though Internet Explorer browser component) that could still be used as attack vector?
We're aware of one - Windows Media Player (WMP) uses jscript.dll directly and will still be able to do so when our micropatch is applied. WMP allows displaying a remote web site when playing certain files but the user has to confirm a security warning for that. This was the reason we decided not to micropatch WMP as well.
Q: How can I deploy this micropatch in my organization's network?
Contact sales@0patch.com for our Enterprise offering (including central management, setting patching policies, group management etc.). We'll set you up with some trial licenses and technical support for making your deployment smooth and quick.
Cheers!
@mkolsek
@0patch