Chrome issue 1196683 (CVE-2021-21220) vulnerability analysis

Introduction

Note: I have not done a very thorough analysis of this vulnerability, so I will be relatively conservative in some of my conclusions.

Basic information about the vulnerability:

  • Product: chrome

  • Component: v8

  • Type: rce

  • Release date: 2021.04.12

Locating the patch

Since the author who announced the vulnerability initially marked it as 0day, I guess the patch should have been released on 4.12.

467835344118695418.jpg

So after locating it, you notice that there are two related security patches as follows:

  • [compiler] Fix bug in RepresentationChanger::GetWord32RepresentationFor (If1eed719) · Gerrit Code Review (googlesource.com)

    https://chromium-review.googlesource.com/c/v8/v8/+/2817791 @a

  • [compiler][x64] Fix bug in InstructionSelector::ChangeInt32ToInt64 (Ib4ea738b) · Gerrit Code Review (googlesource.com)

    https://chromium-review.googlesource.com/c/v8/v8/+/2820971 @b

I thought it was more likely that the patch would be @a because of the vulnerability exploit 16040 written by the previous writer. It turns out that the exploit still fails to trigger without adding the @a patch, because the @b patch has already been added in that version. So we can deduce that @b is the ultimate patch for this vulnerability.

image.png

After removing the patch, the vulnerability was found to be triggered. Verification is complete.

Patch Analysis Revisit the patch:

image.png

Notice the following details:

The vulnerability occurs in the instruction selector session

The comment contains an important keyword, signed-extended

After checking Sign extension - Wikipedia (https://en.wikipedia.org/wiki/Sign_extension), we can locate the following information:

  • movsx: move with sign extension
  • movzx: move with zero extension

To understand the difference between these two analogies, revert to poc:

image.png

Regarding the number arr[0], it should become more interesting to use a binary representation:

image.png

As you can see, the number arr[0] is 1 at bit 32. There are two ways to interpret the 1 here:

  • If the number is unsigned, the 1 is entered as a value.

  • If the number is signed, the 1 is entered as a symbol.

In conjunction with the information that this optimization occurs in the instruction selector, see IR:

image.png

In this case, it is clear that Int64Add corresponds to the (arr[0] ^ 0) + 1 operation. And the result of (arr[0] ^ 0) should be computed by 81. Here, it leaves a question.

Is the 1 in 81 used as a symbol, or is it used as a value?

Analyze the jit function:

image.png

It is easy to conclude that the value of the node on the left should be used as a symbol.

However, looking at the patch:

image.png

Since the case above uses the kX64Movl instruction, we can see that 1 is used as a value.

Another key to this vulnerability is the optimization of the EarlyOptimization link, which optimizes x ^ 0 to the form x.

From here, the root cause of the vulnerability can be summarized:

When ChangeInt32ToInt64 converts a value, regardless of whether the representation is signed or unsigned, the top 1 should be treated as a symbol, not as a value, which was the case before this patch.

Exploit

There are at least three possibilities for learning how to write an exploit for this vulnerability:

Familiarity with the exploit cve-2020-16040 in the analysis, resulting in oob

See below, causing an oob

Using range, causing type confusion, there may be such possibilities.

The second method is described in detail here, the original author’s exp contains the following key code:

image.png

It’s obvious here:

  • The code in red is responsible for triggering the vulnerability.

  • The code in blue is responsible for passing information, so debug the blue part to understand how to exploit it.

Blame

After the blame operation, it was discovered that the vulnerability code was originally introduced in the following case:

  • Issue 2183923003: stubs,interpreter] Optimise SMI loading for 64-bit targets. - Code Review (chromium.org)

​ (https://codereview.chromium.org/2183923003)

So I’ve located the vulnerability myself for a long time, but testing both chrome versions 17 and 18 did not work, which may have something to do with the optimizations needed to trigger the vulnerability. But I still think 2183923003 is the original vulnerability case.

Author

Gongzhuzengmewabishi@@WEBIN.LAB - DBAPPSecurity