템플릿 객체 주입

Template Object Injection

설명

템플릿 객체 주입은 사용자가 제어하는 객체(req.body, req.query 등)를 템플릿 엔진의 locals/context 인자로 그대로 전달할 때 발생합니다. 많은 Node.js 템플릿 엔진(Handlebars, EJS, Pug 등)은 locals 안의 특수 키(layout, filename, settings, partials, helpers 등)를 템플릿 동작/파일 경로에 영향 주는 옵션으로 해석합니다. 공격자는 이러한 특수 키를 요청에 삽입하여 템플릿의 레이아웃/인클루드 파일 경로를 바꾸거나 내부 옵션을 조작함으로써, 로컬 파일 읽기(LFR) 또는 원격 코드 실행(RCE)까지 유발할 수 있습니다. 예: {"layout":"../../../../etc/passwd"}, {"filename":"/etc/passwd"}, {"settings":{"views":"/"}} 등을 주입해 민감 파일을 노출시키거나, 엔진/런타임 옵션을 변경해 코드가 평가되도록 만들 수 있습니다.

잠재적 영향

  • 로컬 파일 노출(LFR): layout/filename/settings 등의 키를 주입해 임의 경로의 파일을 템플릿으로 읽어 민감 정보가 유출될 수 있음.

  • 원격 코드 실행(RCE): 일부 엔진/옵션 조합에서 사용자 입력이 코드로 평가되도록 유도하여 서버 측 임의 코드 실행이 가능할 수 있음.

  • 템플릿/뷰 조작: 의도하지 않은 레이아웃, partials, helpers 주입으로 화면 변조, 보안 검증 우회, 비즈니스 로직 혼선을 유발.

  • 정보 노출 및 권한 상승: 설정 객체(settings, runtimeOptions 등) 변경으로 디버그 정보 노출, 경로 탐색, 추가 취약점 연계 공격 가능.

해결 방법

  • 화이트리스트 기반 전달: 템플릿에 필요한 키만 명시적으로 선택해 새 객체에 담아 전달하세요(예: { name, bio } 만). 전체 req.body/req.query를 넘기거나 스프레드({...req.body})를 사용하지 마세요.

  • 특수/예약 키 차단: layout, filename, views, partials, settings, helpers, runtimeOptions 등 템플릿 제어 키는 사용자 입력에서 제거하거나 덮어쓰지 못하게 하세요.

  • 스키마 검증: Joi/Zod 등으로 전달할 locals의 스키마를 정의해 타입/값 범위를 검증하세요. 알 수 없는 키는 거부하세요.

  • 템플릿 엔진 보안 설정: 가능한 경우 코드 평가 기능 비활성화, 안전 모드 사용, include 경로 제한(고정 디렉터리) 등을 적용하세요.

취약한 코드 및 안전한 코드 예시

취약한 코드

안전한 코드

설명:

  • 취약한 코드: req.body 전체를 render의 두 번째 인자로 넘겨 템플릿 엔진이 해석하는 특수 키(layout, filename, settings 등)까지 공격자가 주입할 수 있습니다. 이로 인해 파일 경로 조작을 통한 LFR 또는 엔진 옵션 조작을 통한 RCE로 악용될 수 있습니다.

  • 안전한 코드: 템플릿에서 실제로 필요한 키만 화이트리스트로 선별하여 새 객체에 담아 전달합니다. 이렇게 하면 사용자 입력이 템플릿 제어 키를 덮어쓰거나 새로운 키를 주입할 수 없으므로 LFR/RCE 가능성이 차단됩니다.

참조

Last updated