For the third time this year, Google’s Chrome browser has quietly received a security update together with the dreaded words, “Google is aware that an exploit […] exists in the wild.”
In this case, the bug is officially dubbed CVE-2022-1364: Type Confusion in V8.
V8 is Google’s JavaScript engine – the same one that’s used by Edge and many other mainstream browsers.
The V8 engine is also used in node.js
, a standalone JavaScript programming ecosystem that’s very widely used these days as a server application language.
How bad is this bug?
We can’t tell from Google’s downplayed warning, but about a month after the company’s first zero-day fix of the year, it published a fairly dramatic follow-up report.
In that case, Google wrote that the bugs uncovered had been traced back to two different North Korean cybercrime groups, and that attacks had apparently spanned the media, IT, cryptocurrency and fintech industries.
We’re not aware of any follow-up report for last month’s emergency patch – it’s possible, after all, that Google simply hasn’t traced the second lot of attacks back to their source yet…
… but, as we remarked last time, and the time before: patch now!
Why remain behind when you can now be ahead of the crooks?
(For advice on how to check and what version numbers to look for in both Chrome and Edge, see our What to do? section below.)
Type confusion explained
“Type confusion” bugs are a class of memory mismanagement flaw where a memory block that’s supposed to used by one sort of calculation inadvertently gets consumed and trusted by a different algorithm.
For example, mixing up a 64-bit unsigned integer and a 64-bit floating point number will typically throw your calculation off horrendously, because the internal layouts of the two number formats are incompatible.
A 64-bit unsigned integer is just a string of bits that directly represents a number from 0 to 264-1.
But a double-precision float consists of three numeric parts packed into 64 bits, with one bit representing the sign, 11 bits representing the magnitude of the number (from the super-tiny 2-1022 to the super-massive 21023, plus 52 bits representing the fractional part of the number.
So, the number 42 comes out as the following binary strings when packed into 8-byte memory blocks (we’ve used hexadecimal, not binary, to save space):
42 decimal packed as 64-bit unsigned --> 0000 0000 0000 002A 42 decimal packed as 64-bit double --> 4045 0000 0000 0000
The double value isn’t treated as a simple bit-string, but is broken down in binary as follows:
404 --> 1 sign bit = 0 (positive) 11 exponent bits = 10000000100 (value 1028; subtract 1023 giving 5; exponent is 25 = 32) 50000... --> binary fraction = 0101000.... (add 1, giving binary 1.01010, or decimal 1.3125) Multiply the fraction 1.3125 × 32 to get 42.0
What if you mix up the encodings?
If you mix the two encodings up, then you get the following bizarre results, turning the 64-bit integer version of 42 into a truly minuscule decimal fraction, and the floating-point version of 42.0 into an absurdly large integer:
0000 0000 0000 002A processed as a double float --> 2.0750757125332 x 10-322 4045 0000 0000 0000 processed as 64-bit unsigned --> 4,631,107,791,820,423,168
As you can see, even confusing integers and floating point numbers could result in dangerous miscalculations, especially if the code that misinterprets the raw data assumes that the value can be trusted because it was already checked when the data was originally computed and stored.
What if you mix up something much worse?
In real life, especially in complex software such as scripting engines, type confusion between two more complex types of memory block can have even more dramatic consequences.
For example, imagine that, as an attacker, you have a way to build an icon from a bitmap you provide, and your icon gets packed into a memory block something like this:
integer value giving width of cursor icon integer value giving height of cursor icon string of width × height bytes denoting icon transparency
For a 16×16 pixel icon, assuming 8 bytes for each of the two integers, this gives you a way to encode a precise pattern of up to 8 + 8 + 256 = 272 bytes in a memory block used by the app to represent an icon object.
As long as the app only ever interprets and uses this icon data to reconstruct and display your icon, and validates that the width and height are safe to use, you can’t do any harm (except, perhaps, to display a weird icon).
But now imagine that immediately after creating the icon memory buffer, you could trick the app into thinking that the data it just stored was a completely different sort of object, such as one structured as follows:
integer value giving number of iterations to try integer value giving size of output to create memory pointer to function called to generate each data value memory pointer denoting where to output the generated data
This is an imaginary situation, of course (it’s not representative of any known Chrome or JavaScript engine bug we’re aware of, now or in the past), but it helps you paint a mental picture of how just dangerous this sort of type confusion could be.
Instead of having the treacherous power to mix up the numeric values 42 and 4.6 million million million, as we saw in the integer-versus-float type confusion above, you’d potentially have the power to “create” an innocent-looking icon that subsequently, and deliberately, misdirected the execution of the app.
You could not only rig things up so that the app would call unwanted code in future (the generator function), but also so that it would write data of your choosing (the output of the generator), in an amount of your choosing (the iteration count), to a memory location of your choosing (via the output pointer).
What to do?
As always, ensure you have the latest version of Chrome.
Google has published two relevant security advisories: one for Windows, Mac and Linux, and a second but largely identical bulletin for Android.
Your Chrome version on all those platforms should now be Chrome 100.0.4896.127 (or later), released on 2022-04-14.
Google’s Play Store doesn’t give precise details for Android users, saying, in its typically non-committal way, that the “Current Version varies with device”. (The most recent date given for an update, however, is listed as 2022-04-14.)
We notice that numerous unofficial Android download sites (no, we’re not going to recommend any; stick to Google Play if you can) already have the 100.0.4896.127 build available, so we’re guessing that many devices, presumably including Google’s own phones, therefore already have the latest version downloaded or ready to download.
Microsoft Edge received an update on 2022-04-15; we don’t know whether it includes this fix, but if you want to get it anyway, you’re looking for Edge 100.0.1185.44.
If you haven’t updated yet, or if you’re not sure, you can do this:
- Google Chrome. Three-dot menu (⋮) > Help > About Chrome.
- Microsoft Edge. Settings and more (…) > Help and feedback > About Microsoft Edge.
- Android. Open the Play Store app, click your account icon and check for app updates.
Don’t delay; do it today!
Charlie
“But now imagine that immediately after creating the icon memory buffer, you could trick the app into thinking that the data it just stored was a completely different sort of object ….”
And how does that happen? Buffer overrun at the C level?
Paul Ducklin
In this case, the underlying cause of the type confusion (for example, an incorrectly modified type identifier field at the start of the block) is not specified. Various memory bugs spring to mind, including use-after-free, buffer overflow, some sort of race condition, and so on.
But type confusions can also happen without any memory overflow needed to mess up a type identifier field. For example, if you can find a function that’s designed to be called with a range of different but related object types, but that doesn’t check those object types carefully enough (imagine a function that’s supposed to work only with 32, 64 or 128 integers but that inadvertently accepts 32, 64 and 128 bit floats without flagging an error, and thus processes them incorrectly), you may be able to feed it an object of type Y or Z without the function rejecting it for not being of type X. Thus you might be able to provoke a type confusion bug just by passing in the wrong sort of parameter, rather than by manipulating part of the content of an existing object in memory.
Kyle
For those interested, here’s one of the previous type confusion exploits, explained in technical detail:
https://googleprojectzero.github.io/0days-in-the-wild/0day-RCAs/2021/CVE-2021-30551.html
Pretty scary how this works.
Big Al
FWIW, the three dot menu option does not update the browser, for whatever reason. The latest update is available at Google Play Store, though.