위험한 동적 메서드 접근에 의한 코드 주입

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