위지윅 에디터와 XSS 대응 방법 with 타임리프
프로젝트에 위지윅 에디터를 사용하기위해 CKEditor 오픈소스를 적용했다.
사용자가 굵은 글씨, 기울임 등 에디터를 통해 작성한 내용을 서버에서 저장하기위해서는
태그를 함께 저장해야한다.
태그를 함께 저장해야할텐데 XSS 공격은 어떻게 대응할까?
동작 예시를 통해 대응 방법을 이해해보자.
사용자가 의도적으로 굵은 글씨를 표현하는 태그인 <strong> 태그를 다음과 같이 삽입했다고 하자.
에디터를 통해 서버로 넘어와 저장되는 값은 다음과 같다.
'<' 글자가 "<"로 저장되었다.
html에서 <, >, & 는 같은 특수한 기능을하는 문자들이므로
서버에서는 안전한 문자로 저장할 필요가 있기에 변환하여 저장한 것이다.
그러면 의도적으로 태그를 삽입하는것이 아닌
에디터를 통해서 굵은 글씨를 작성해보자.
서버에는 어떻게 저장이 될까?
DB에는 '<' 문자가 안전하게 변환되지 않고 '<' 문자 그대로 저장되었다.
그렇다. 라이브러리에서는 XSS를 방지하고자
에디터를 통한 태그만 '<' 문자 그대로 서버에 전송하는 것이다.
content
<p><strong>strong</strong></p>
타임리프 th:text를 통해 위의 content를 출력해보자.
타임리프 th:text
<div th:text="${poster.content}"></div>
텍스트 그대로 출력이 된다. 정상적인 태그 삽입인 에디터를 통해서 <strong> 태그를 잘 넣었는데
태그를 문자 그대로 출력해버리는 것이다.
타임리프는 문자 그대로 출력하지 않고 태그를 읽어 출력하는 "th:utext"를 제공한다.
타임리프 th:utext
<div th:utext="${poster.content}"></div>
태그가 적용되어 굵은 글씨로 표현된다.
html에서 <, >, &와 같은 특수문자를 변환하는것을 이스케이프라고 한다.
th:text는 이스케이프를 적용해서 문자 그대로를 출력하여 특수 기능은 동작하지 않게한다.
th:utext는 unescape이다. 특수 기능이 동작하게 렌더링한다.
정리
위지윅 에디터는 악의적인 태그 입력을 방지하는 기능을 포함하고 있다.
그래서 서버로 전송할때 정상적인 태그는 그대로 전달하지만
악의적인 태그는 이스케이프가 적용되어 변환되어 전달한다.
서버에서는 이 전송되는 데이터를 그대로 저장한다고 가정하자.
타임리프를 통해 서버에 저장된 데이터를 읽을때
이스케이프를 고려하여 읽음으로써 XSS를 방지할 수 있다.
th:text를 통해 서버에 저장된 문자열 그대로 출력할 수 있지만
th:utext를 통해 이스케이프 문자를 구분하여 태그로쓸지말지를 파악해서 출력한다.