Sanitize-HTML: 안전한 웹 애플리케이션을 위한 필수 도구
웹 애플리케이션에서 사용자 입력을 처리할 때 가장 중요한 것은 보안이다. XSS(Cross-Site Scripting)
공격은 여전히 OWASP Top 10
웹 애플리케이션 보안 위험 중 하나로 꼽히고 있다. 이러한 위험으로부터 우리의 애플리케이션을 어떻게 보호할 수 있을지 알아보도록 한다.
Sanitize-HTML이란?
sanitizing : 살균하다
Sanitize-HTML
은 사용자가 제공한 HTML을 안전하게 정화하여 악의적인 스크립트를 제거하는 Node.js 라이브러리이다. 이 라이브러리는 신뢰할 수 없는 HTML과 악의적인 JavaScript를 제거하면서도 안전한 HTML 태그와 속성은 유지한다.
주요 기능
- 허용된 HTML 태그만 남기고 나머지는 제거
- 안전하지 않은 속성 제거
- 스크립트 태그 및 이벤트 핸들러 제거
- URL 스키마 검증
- 스타일 속성 필터링
- 커스터마이즈 가능한 설정
사용 방법
설치
$ npm install sanitize-html
기본 사용법
- 악의적인 스크립트를 제거하고 안전한 HTML만 남긴다.
const sanitizeHtml = require("sanitize-html");
const dirty =
'<p>안전한 HTML입니다.</p><script>alert("악의적인 코드!");</script>';
const clean = sanitizeHtml(dirty);
console.log(clean); // 출력: <p>안전한 HTML입니다.</p>
고급 설정
- 허용된 태그, 속성, iframe 호스트 등을 설정할 수 있다.
const options = {
allowedTags: ["b", "i", "em", "strong", "a"],
allowedAttributes: {
a: ["href"],
},
allowedIframeHostnames: ["www.youtube.com"],
};
const clean = sanitizeHtml(dirty, options);
실제 사용 사례
-
블로그 플랫폼
- 사용자가 작성한 게시글의 HTML 컨텐츠 정화
- 댓글 시스템의 기본 HTML 태그 허용
-
CMS 시스템
- WYSIWYG 에디터 출력물 정화
- 사용자 생성 컨텐츠 관리
-
채팅 애플리케이션
- 메시지 내 HTML 포맷팅 허용
- 이모지와 기본 서식 지원
보안 설정 모범 사례
최소 권한 원칙 적용
- 필요한 기능에 한해서만 허용된 태그와 속성을 설정한다.
const strictOptions = {
allowedTags: ["p", "b", "i", "em", "strong", "a"],
allowedAttributes: {
a: ["href"],
},
allowedSchemes: ["http", "https", "ftp", "mailto"],
allowedSchemesByTag: {},
allowedSchemesAppliedToAttributes: ["href", "src", "cite"],
allowProtocolRelative: true,
};
옵션
allowedTags
: HTML에서 허용할 태그 지정. 지정한 태그 외에는 필터링된다.allowedAttributes
: HTML 요소에 허용할 속성 제어. 속성을 지정하지 않으면 모든 속성이 허용된다.allowedStyles
: HTML 요소에 허용할 스타일 속성과 값의 패턴 지정. 스타일 속성을 지정하지 않으면 모든 스타일이 허용된다.allowedClasses
: HTML 요소에 허용할 CSS 클래스 제어. 클래스를 지정하지 않으면 모든 클래스가 허용된다.allowedIframeDomains
: <iframe> 요소의 src 속성에서 허용할 도메인 제한.allowedIframeHostnames
: <iframe> 요소의 src 속성에서 허용할 호스트 이름 제한.allowIframeRelativeUrls
: 상대 URL 허용 여부 지정.allowedSchemes
: URL의 스키마(프로토콜) 허용. 예를 들어, [‘http’, ‘https’]로 설정하면 http://와 https:// URL만 허용된다.allowedSchemesByTag
: 특정 HTML 태그에 대한 허용 스키마 지정. 예를 들어, { a: [‘http’, ‘https’], img: [‘data’] }로 설정하면<a>
태그의 href 속성은 http와 https URL만 허용하고,<img>
태그의 src 속성은 data URL만 허용한다.allowedSchemesAppliedToAttributes
: 특정 속성에 대한 스키마 제한. 예를 들어, [‘href’, ‘src’]로 설정하면 href 및 src 속성에만 스키마 제한이 적용된다.allowedScriptDomains
: 스크립트 태그의 src 속성에서 허용할 도메인 제한.allowedScriptHostnames
: 스크립트 태그의 src 속성에서 허용할 호스트 이름 제한.allowProtocolRelative
: 프로토콜 상대 URL (//example.com)을 허용 여부 지정.allowVulnerableTags
: 보안 취약한 태그 허용 여부 지정. 예를 들어, <iframe> 및<script>
태그는 보안 취약점을 가질 수 있으므로 기본적으로 허용되지 않는다.textFilter
: 텍스트 내용을 필터링하거나 수정하는 사용자 정의 함수 제공.exclusiveFilter
: 특정 HTML 태그를 필터링할지 여부를 제어하는 사용자 정의 함수 제공.nestingLimit
: HTML 태그의 중첩 제한. 예를 들어, { div: 3 }로 설정하면 <div> 태그는 최대 3단계까지만 중첩될 수 있다.nonTextTags
: 텍스트가 아닌 내용을 가진 HTML 태그 지정. 예를 들어, [‘script’, ‘style’]로 설정하면<script>
및<style>
태그는 텍스트 필터링에서 제외된다.parseStyleAttributes
: 스타일 속성 파싱 여부 지정. 기본적으로 true로 설정되어 있으며, false로 설정하면 스타일 속성이 제거된다.selfClosing
: 빈 요소 (예:<img>
,<br>
) 처리. 기본적으로 true로 설정되어 있으며, false로 설정하면 빈 요소가 닫는 태그를 가져야 한다.transformTags
: 특정 HTML 태그 변환. 예를 들어, { img: ‘image’ }로 설정하면<img>
태그가<image>
태그로 변환된다.parser
: 사용자 지정 파서 지정. 기본적으로 HTMLParser2를 사용하며, 다른 파서를 사용하려면 해당 파서를 지정해야 한다.disallowedTagsMode
: 불허용 태그에 대한 처리 모드 지정. ‘discard’ (기본값)로 설정하면 불허용 태그는 제거되고, ‘escape’로 설정하면 태그가 이스케이프 처리된다.enforceHtmlBoundary
: true로 설정하면 <html> 태그 이전과 이후의 문자를 모두 삭제. 기본적으로 false로 설정되어 있다.
URL 검증 강화
- 사용자 입력의 URL을 검증하여 악의적인 링크를 차단한다.
- 특히, 외부 링크의 경우 허용된 도메인만 허용하도록 설정한다.
const urlCheckOptions = {
allowedTags: ["a"],
allowedAttributes: {
a: ["href"],
},
transformTags: {
a: (tagName, attribs) => {
if (attribs.href) {
// URL 검증 로직 추가
if (!/^https?:\/\//i.test(attribs.href)) {
return false;
}
}
return {
tagName,
attribs,
};
},
},
};
스타일 속성 제한
- 스타일 속성을 허용할 경우, 허용된 스타일만 적용되도록 설정한다.
- 이를 통해 악의적인 스타일 속성을 차단할 수 있다.
const styleOptions = {
allowedTags: ["p", "span"],
allowedAttributes: {
p: ["style"],
span: ["style"],
},
allowedStyles: {
"*": {
color: [
/^#(0x)?[0-9a-f]+$/i,
/^rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/,
],
"text-align": [/^left$/, /^right$/, /^center$/],
"font-size": [/^\d+(?:px|em|%)$/],
},
},
};
결론
Sanitize-HTML은 웹 애플리케이션의 보안을 강화하는 필수적인 도구로, 적절한 설정과 함께 사용하면 XSS 공격으로부터 효과적으로 보호할 수 있으며, 동시에 사용자에게 풍부한 HTML 기능을 제공할 수 있다. 보안과 기능성의 균형을 맞추는 것이 중요하며, 정기적인 설정 검토와 업데이트를 통해 최신 보안 위협에 대응해야 한다.