취약점 개요

ejs 템플릿 엔진에서 발생하는 취약점으로, 입력 값 검증 로직이 누락되어 사용자가 템플릿 주입을 통해 RCE를 실행할 수 있다.

영향

SSTI, RCE

취약 버전

  • ejs v3.1.10 이전 버전(최신 릴리즈)

환경 구성

  • express v4.21.2
  • ejs v3.1.9

취약점 분석

  • app.js 파일을 살펴보면, express의 ejs 템플릿 엔진을 사용하여 page.ejs를 렌더링하고, GET 메서드로 전송된 값을 req.query 매개변수를 통해, ejs 템플릿에 넘겨주고 있다.

app.js

page.ejs

  • ejs.js를 확인해보면 442번째 줄에서 렌더링된 값을 저장하고 있으며, 457번째 줄에서 req.query 매개변수로 넘겨받은 값을 data에 저장하고 있다.

ejs.js

  • 브라우저에 /?id=aaaaa 값을 넘겨주면 data에 key, value 형식으로 저장된다.

사진은 Universe7202님의 블로그를 참고했습니다.

  • 이후 ejs.js의 476번째 줄을 확인해보면, viewOpts 변수에 data.settings[‘view options’] 를 저장하고 data.settings에 [‘view options’] 값이 존재한다면 shallowCopy 함수를 실행한다.
  • ejs.js의 1087번째 줄에서 shallowCopy의 실행 흐름을 보면 opts의 값이 null이나 underfined가 아니면 두번째 인자값(viewOpts)을 첫번째 인자값(opts)에 복사한다.

viewOpts

  • ejs.js의 572번째 줄을 보면, ejs 컴파일 함수에 대한 내용이 담겨 있는데 opts.[함수명]을 임의로 덮어씌울 수 있다면 RCE가 발생한다. 이 문서에서는 581번째 줄에 있는 escapeFn 함수를 덮어씌워 RCE를 발생시킬 것이다.
  • 단, escapeFn을 덮어씌우려면 선행조건으로 opts.client를 참으로 만들어야 하며, 최종적으로 escapeFn.toSting()을 통해 우리가 원하는 RCE 코드를 집어넣을 수 있다

compile

RCE 발생 위치

exploit

  • 도커를 이용해 취약 환경을 구성 후, http://localhost:3000 포트로 접속

도커 컨테이너 실행

page.ejs

  • 실습에 앞서 입력한 값이 제대로 들어가는지 확인하기 위해 디버그 모드를 실행한다.
  • debug 파라미터에 값을 넣고 도커 컨테이너 로그를 확인해보면 내부 디버깅이 활성화되어 값이 찍히는것을 확인할 수 있다.

debug 활성화

도커 컨테이너 로그

  • 이제 분석한 내용을 실제로 실습해보자. 사용자가 입력한 값은 req.query 매개변수를 통해 data에 저장되고, data.settings에 [‘view options’]이 존재한다면 shallowCopy를 통해 값이 opt에 저장된다.
  • 우선 opt값이 변조되는지 확인하기 위해 settings[View Options][client]=true로 패킷을 전송하면 도커 컨테이너 로그에 찍히는 값이 추가된다. 이를 통해 opts.client가 참이 된 것을 확인할 수 있다.

opts.client 값 추가

도커 컨테이너 로그

  • opts.client에 이어서 escapeFn에 값을 넣어보면 에러가 출력되고, 도커 컨테이너 로그를 확인해보면 입력한 값은 escapeFn에 저장된것을 확인할 수 있다.

opts.escapeFn 값 추가

도커 컨테이너 로그

  • 이제 분석한 내용을 실제로 실습해보자. 우리가 입력한 값은 req.query 매개변수를 통해 data에 저장되고, data.settings에 [‘view options’]이 존재한다면 shallowCopy를 통해 값이 opt에 저장된다.
  • 이를 통해, 지정한 디렉터리 경로의 파일을 읽어오는 RCE를 실행시킬 수 있다. (단, 함수에 인자값을 잘못 주면 서버가 종료되니 주의할것)

RCE 실행

도커 컨테이너 로그

대응 방안

대응 방법설명
버전 패치ejs v3.1.10으로 패치

출처

NVD - CVE-2023-29827CVE-2023-29827 Detail Modified This CVE record has been updated after NVD enrichment efforts were completed. Enrichment data supplied by the NVD may require amendment due to these changes. Current Description ejs v3.1.9 is vulnerable to server-side templatnvd.nist.gov

POC · EJS@3.1.9 has a server-side template injection vulnerability (Unfixed) · Issue #735 · mde/ejsEJS has a server-side template injection vulnerability. You have fixed some server-side template injection vulnerabilities recently, such as CVE-2022-29078, CVE-2023-29827. But there’s one more tha…github.com