V8 엔진, DevTools 감지 우회 기술의 숨겨진 원리

by DD
2개월 전
조회수 18

브라우저의 DevTools는 객체 내부를 검사해야 하므로, JavaScript에서 감지 가능한 동작을 유발함

봇(Bot) 감지 기술은 console API 호출을 통해 DevTools 존재를 감지하는 방법을 발견함

V8 엔진은 이 문제를 해결하기 위해 패치를 적용했지만, 프록시(Proxy) 기반의 새로운 우회 기술이 등장함

프록시(Proxy)의 ownKeys 트랩(Trap)을 활용하여 DevTools 감지를 우회하는 기술의 원리를 분석함

오류 스택(Error Stack) Getter를 이용한 초기 감지 기술

초기 봇 감지 기술은 오류 객체(Error Object)의 `stack` 속성에 사용자 정의 getter를 설정하여 DevTools의 존재를 감지했다. `console.debug()` 호출 시, DevTools가 활성화되면 `stack` getter가 실행되어 감지 플래그를 설정하는 방식이다. 하지만 V8 엔진은 이 취약점을 해결하기 위해 `getErrorProperty()` 함수를 도입하여 ScriptId 검사(ScriptId Check)를 추가했다.

V8 패치의 한계와 우회 경로

V8 패치는 `ScriptId`를 검사하여 사용자 정의 getter 실행을 막았지만, own property가 아닌 getter는 이 검사를 우회할 수 있었다. `GetOwnPropertyDescriptor`가 descriptor를 반환하지 않으면 `object->Get()`이 직접 호출되어 `ScriptId` 검사가 무시된다. 이러한 구조적 허점을 통해, 패치 이후에도 DevTools 감지 회피가 가능했다.

프록시(Proxy)를 활용한 새로운 감지 기술

새로운 기술은 프록시(Proxy)의 `ownKeys` 트랩(Trap)을 활용하여 DevTools 감지를 우회한다. `console.groupEnd()`에 프록시를 전달하면, DevTools는 객체의 속성을 열거하기 위해 `DebugPropertyIterator`를 사용한다. 이 과정에서 프록시의 `ownKeys` 트랩이 실행되어 감지 신호를 발생시킨다. ECMAScript 명세(ECMAScript Specification)는 프록시의 own property keys를 얻기 위해 `ownKeys` 트랩을 호출하도록 강제한다.

프록시(Proxy) 기반 감지 기술의 동작 원리

프록시 기반 감지 기술은 여러 C++ 레이어를 거쳐 동작한다. Inspector는 인수를 직렬화하기로 결정하고, 프록시 검사(Proxy Check)는 표면적인 검사만 수행한다. `DebugPropertyIterator`는 프로토타입 체인을 탐색하며, `FillKeysForCurrentPrototypeAndStage` 함수는 키를 수집한다. `kEnumerableStrings` 단계에서 `KeyAccumulator::GetKeys`가 프록시에서 `ownKeys` 트랩을 호출한다. ECMAScript 명세(ECMAScript Specification)는 이 동작을 강제한다.

기술적 함의 및 보안 위협

이러한 기술은 브라우저 환경에서 봇(Bot) 탐지 및 안티-봇(Anti-Bot) 기술 간의 끊임없는 경쟁을 보여준다. DevTools 감지 회피는 웹 애플리케이션의 보안을 약화시킬 수 있으며, 악의적인 행위자가 웹 스크래핑(Web Scraping), 자동화된 공격(Automated Attacks) 등에 악용할 수 있다. 따라서, 웹 개발자는 이러한 기술 동향을 지속적으로 주시하고, 데이터 격리 아키텍처(Data Isolation Architecture)데이터 미저장 정책(Zero-Retention Policy)과 같은 보안 조치를 강화해야 한다.

The ECMAScript spec forces V8 to leak whether DevTools is open