설명
템플릿 엔진(Mustache 등)에서 기본 HTML 이스케이프 함수를 무력화하면, HTML 특수 문자가 자동 이스케이프되지 않아 악의적인 스크립트가 그대로 출력될 수 있습니다. Mustache.js에서는 Mustache.escape를 사용자 정의 함수로 덮어쓸 수 있으며, 이를 입력을 그대로 반환하는 함수로 바꾸면 XSS(Cross-Site Scripting) 공격으로 이어질 수 있습니다.
잠재적 영향
- XSS 공격 가능 (크로스사이트 스크립팅): 공격자가 악의적인 스크립트를 삽입해 사용자의 브라우저에서 실행될 수 있습니다.
- 정보 탈취: 사용자의 쿠키, 세션 정보 등이 탈취될 수 있습니다.
- 사이트 변조 또는 서비스 신뢰도 저하: 웹페이지가 공격자에 의해 변조될 수 있습니다.
해결 방법
- HTML 텍스트에 값을 출력할 때 템플릿의 기본 이스케이프를 유지하세요.
- 입력을 그대로 반환하는 함수로
Mustache.escape를 덮어쓰지 마세요. - URL, JavaScript, CSS 등 다른 출력 문맥은 해당 문맥에 맞게 검증·인코딩하세요. HTML 이스케이프만으로 모든 문맥이 보호되지는 않습니다.
예시
변경 전
javascript
const Mustache = require('mustache');
// BAD: Mustache의 HTML 이스케이프 함수를 입력 그대로 반환하도록 덮어씀
Mustache.escape = function(text) {
return text;
};
const unsafeTemplate = '<div>{{userInput}}</div>';
const html = Mustache.render(unsafeTemplate, { userInput: req.query.text });
변경 후
javascript
const Mustache = require('mustache');
// GOOD: Mustache의 기본 이스케이프 동작을 그대로 사용
const safeTemplate = '<div>{{userInput}}</div>';
const html = Mustache.render(safeTemplate, { userInput: req.query.text });
설명:
- 변경 전:
Mustache.escape를 입력 그대로 반환하도록 덮어쓰면, 템플릿에 삽입된 사용자 입력값이 HTML로 이스케이프되지 않아 악성 스크립트가 그대로 브라우저에 삽입되고 실행될 수 있습니다. - 변경 후: Mustache의 기본 이스케이프 동작을 유지하면, 이 예제의 HTML 텍스트 위치에 들어갈 특수 문자가 이스케이프됩니다. 변경 전·후는 별도의 실행을 가정하며, 이미 덮어쓴 전역 함수를 단순히 다시
require한다고 복구되지는 않습니다.