코드 인젝션 (eval/동적 템플릿 컴파일)
Code Injection
설명
코드 인젝션은 사용자 입력을 코드처럼 평가하거나 템플릿 엔진이 실행할 표현식으로 넘길 때 발생합니다. 예를 들어 eval, new Function, setTimeout/setInterval에 문자열 코드를 전달하거나, Pug/EJS/Handlebars/Lodash 템플릿에 사용자 입력을 그대로 컴파일/렌더링하면 공격자가 임의의 코드를 실행할 수 있습니다. 서버에서는 RCE(원격 코드 실행)로 이어질 수 있고, 클라이언트에서는 XSS로 스크립트가 실행될 수 있습니다.
잠재적 영향
원격 코드 실행(RCE): 서버에서 임의 자바스크립트가 실행되어 시스템 명령 실행, 파일 접근, 내부망 스캔 등이 가능해집니다.
권한 상승: 애플리케이션 권한으로 시스템 자원에 접근하거나 관리자 권한 획득 시도로 이어질 수 있습니다.
데이터 유출/변조: DB 조회·수정, 환경변수·토큰 탈취 등 민감 정보가 노출되거나 변경될 수 있습니다.
크로스 사이트 스크립팅(XSS): 템플릿 결과가 브라우저에 전달될 때 스크립트가 삽입·실행되어 사용자 세션 탈취가 발생할 수 있습니다.
서비스 거부(DoS): 무한 루프·대량 메모리 사용 등의 코드가 실행되어 서비스가 중단될 수 있습니다.
해결 방법
사용자 입력을 eval, new Function, vm.runIn*, setTimeout/setInterval(문자열 인자) 등 코드 실행 API에 절대 전달하지 않습니다.
템플릿 엔진은 고정(상수) 템플릿만 컴파일/렌더링하고, 사용자 입력은 항상 데이터 컨텍스트(예: render(data))로만 전달합니다. 자동 이스케이프를 비활성화하지 말고, EJS의 <%- %> 같은 비이스케이프 출력은 피합니다.
동적 동작이 필요하면 허용 목록 기반 설계(미리 정의된 연산/함수만 매핑)로 구현합니다. 사용자 입력을 코드가 아닌 데이터로만 처리하세요.
setTimeout/setInterval에는 콜백 함수만 전달합니다. 문자열 코드는 사용하지 않습니다.
입력값에 대해 맥락별 이스케이프(HTML/URL/JS 컨텍스트)와 검증을 적용합니다.
Node.js vm 모듈은 완전한 샌드박스가 아니므로 보안 경계로 의존하지 않습니다.
취약한 코드 및 안전한 코드 예시
취약한 코드
안전한 코드
설명:
취약한 코드:
eval 및 문자열 기반 setTimeout/setInterval은 입력 문자열을 코드로 실행합니다. 공격자가 임의 자바스크립트를 실행해 파일/환경변수 접근, 네트워크 호출 등 RCE로 이어질 수 있습니다.
사용자 제공 템플릿을 EJS/Pug 등에 그대로 넘기면 서버사이드 템플릿 인젝션(SSTI)이 발생하며, 템플릿 엔진 기능을 악용해 서버 코드 실행 또는 응답 내 스크립트 삽입(XSS)이 가능합니다.
안전한 코드:
허용 목록 기반 연산 매핑을 사용해 입력을 코드로 평가하지 않고, 안전한 함수만 호출합니다.
템플릿은 고정 문자열만 컴파일/렌더링하고, 사용자 입력은 데이터 컨텍스트로 전달하여 템플릿 엔진이 자동 이스케이프하도록 합니다.
setTimeout/setInterval에는 콜백 함수만 전달하여 문자열 코드 실행 경로를 제거합니다.
참조
Last updated