Coordinated Disclosure Timeline

Summary

A type confusion in VisitFindNonDefaultConstructorOrConstruct can be exploited by an attacker to gain code execution in Chrome’s renderer.

Product

Chromium

Tested Version

115.0.5790.98

Details

Type confusion in VisitFindNonDefaultConstructorOrConstruct of Maglev (GHSL-2023-180)

In the maglev implementation of VisitFindNonDefaultConstructorOrConstruct, if new_target is a constant function, then the object will be constructed directly using the initial_map of new_target [1], [2].

void MaglevGraphBuilder::VisitFindNonDefaultConstructorOrConstruct() {
  ...
          compiler::OptionalHeapObjectRef new_target_function =
              TryGetConstant(new_target);
          if (kind == FunctionKind::kDefaultBaseConstructor) {
            ValueNode* object;
            if (new_target_function && new_target_function->IsJSFunction()) {
              object = BuildAllocateFastObject(
                  FastObject(new_target_function->AsJSFunction(), zone(),
                             broker()),
                  AllocationType::kYoung);

This, however, has a couple of problems. First, when passing new_target to FastObject, it does not check whether new_target actually has an initial_map. If new_target is Proxy, then it will try to use the initial_map field [3] in the corresponding JSFunctionData. For functions that do not have an initial_map, this would be null and so this would only result in a NULL pointer dereference, rather than a security issue.

A more serious issue is that, BuildAllocateFastObject does not check whether the constructor field of initial_map is the same as the target function. The implementation in FastNewObject bails out to Runtime::kNewObject when target and the constructor of new_target differ [4], which calls JSObject::New and then calls JSFunction::GetDerivedMap to create the correct initial_map [5] to create the object.

This causes the object created by the maglev implementation to have an inconsistent object layout and map, which causes type confusion.

  1. https://source.chromium.org/chromium/chromium/src/+/ecca8fb3876014c0c5f245df70d7e45e07711e69:v8/src/maglev/maglev-graph-builder.cc;l=5384;bpv=0
  2. https://source.chromium.org/chromium/chromium/src/+/ecca8fb3876014c0c5f245df70d7e45e07711e69:v8/src/maglev/maglev-graph-builder.cc;l=8024;bpv=0
  3. https://source.chromium.org/chromium/chromium/src/+/9fa308f2af6566a1feabf5bafef0240cfc6cce33:v8/src/compiler/heap-refs.cc;l=498
  4. https://source.chromium.org/chromium/chromium/src/+/9fa308f2af6566a1feabf5bafef0240cfc6cce33:v8/src/builtins/builtins-constructor-gen.cc;l=313;bpv=0;bpt=0
  5. https://source.chromium.org/chromium/chromium/src/+/a328097ef1d47f51e76917b80110863037f4f744:v8/src/objects/js-objects.cc;l=2392;bpv=1;bpt=0

Impact

Can be exploited to cause RCE in Chrome renderer

Resources

Blog post Getting RCE in Chrome with incomplete object initialization in the Maglev compiler.

CVE

Credit

This issue was discovered and reported by GHSL team member @m-y-mo (Man Yue Mo).

Contact

You can contact the GHSL team at securitylab@github.com, please include a reference to GHSL-2023-180 in any communication regarding this issue.