위험한 동적 메서드 접근에 의한 코드 주입
Code Injection via Unsafe Dynamic Method Access
설명
사용자 입력으로 결정된 문자열을 전역 객체(window/globalThis/global)의 프로퍼티 키로 사용해 함수를 호출하면, 의도치 않게 eval 또는 Function 생성자 같은 위험한 함수를 실행할 수 있습니다. 전역 객체에는 eval과 Function이 노출되어 있고, 이들을 호출하면 임의 코드가 실행됩니다. 예를 들어 사용자가 name=eval 또는 name=Function 을 전달하면 windowname 또는 globalThisname 호출이 곧바로 코드 실행으로 이어집니다. 공격자는 이를 이용해 악성 스크립트 실행, 민감 정보 접근, 시스템 명령 실행(서버 환경) 등을 수행할 수 있습니다.
잠재적 영향
원격 코드 실행(RCE): 전역 객체의 eval/Function 호출을 유도해 임의 JavaScript 코드를 실행할 수 있습니다.
데이터 유출: 실행된 코드로 쿠키, 토큰, 환경변수 등 민감 정보를 읽고 외부로 전송할 수 있습니다.
데이터 변조/권한 남용: 애플리케이션 상태 변경, 관리자 기능 호출 등 권한 외 동작을 수행할 수 있습니다.
서비스 거부(DoS): 무한 루프나 대량 연산 코드를 실행해 자원을 고갈시킬 수 있습니다.
해결 방법
전역 객체(window/globalThis/global)나 함수 객체에 대해 사용자 입력으로 메서드 이름을 동적 호출하지 않습니다.
허용 목록(allowlist) 기반 디스패치: 전용 API 객체 또는 Map에 허용된 함수만 등록하고, Object.hasOwn(Object.create(null)로 생성) 등으로 키를 검증 후 호출합니다.
기본 거부(default deny): 목록에 없는 이름은 즉시 거부하고, 안전한 기본 동작을 사용합니다.
eval/Function 금지: JSON 파싱, 명시적 조건 분기, 안전한 API 맵 등 대체 수단을 사용합니다. ESLint(no-eval, no-implied-eval)처럼 정적 분석 규칙을 적용합니다.
방어 심화: 브라우저에서는 CSP에서 'unsafe-eval'을 금지하고, Node.js에서는 가능하면 V8 옵션(--disallow-code-generation-from-strings)과 런타임/빌드 정책으로 코드 생성 함수를 차단합니다.
취약한 코드 및 안전한 코드 예시
취약한 코드
안전한 코드
설명:
취약한 코드: 사용자 입력을 전역 객체의 프로퍼티 키로 사용해 함수를 동적으로 호출하고 있습니다. 공격자가 name/action 값을 eval 또는 Function 으로 지정하면, 전달된 문자열이 즉시 코드로 실행되어 임의 코드 실행(RCE)이 발생합니다. 단순 입력 필터링이나 이스케이프는 함수 선택 자체를 막지 못하므로 근본적인 방어가 되지 않습니다.
안전한 코드: 전역 객체를 전혀 사용하지 않고, 전용 API 컨테이너에 허용된 함수만 등록한 뒤 Object.hasOwn과 typeof로 키와 타입을 검증합니다. 목록에 없는 이름은 기본 거부하며, 프로토타입 체인을 제거(Object.create(null))해 우회 가능성을 낮췄습니다. 이로써 사용자가 임의의 eval/Function 등 위험한 함수를 선택해 실행하는 경로가 제거됩니다.
참조
Last updated