개발을 하며 'XSS공격을 조심해라'라는 말을 들어본 적이 있을 것이다. 과연 XSS가 무엇이길래 조심하라는 것인지, 또 어떻게 방지해야하는지 알아보자❗️❗️❗️
먼저, XSS에 대해 알아보기전에 우리는 JavaScript를 사용하면서 각 이벤트에 맞는 태그를 넣기 위해 'innerHTML'이나 'insertAdjacentHTML'을 사용한다.
innerHTML | insertAdjacentHTML | |
---|---|---|
인자 | text(변경할 태그 혹은 텍스트) | position(넣을 위치), text(추가할 태그 혹은 텍스트) |
실행 로직 | 기존의 노드를 추가할 노드로 변경하고, 파싱작업을 한다. | 추가 파싱없이 기존의 DOM tree안에 node를 insert한다. |
하지만 이 두가지 모두 DOM에 직접 넣는다는 방법 때문에 XSS 공격을 받을 위험이 있다.
그렇다면 XSS공격이라는 것은 무엇일까?
XSS(Cross-Site-Scripting)란 다른 웹사이트와 정보를 교환하는 것으로,XSS 공격은 간단하게 말하자면, 웹 애플리게이션에서 웹사이트 관리자가 아닌 이가 웹 페이지에 악성 스크립트를 삽입하는 것을 말한다.
이 공격을 위에서 말했던 innerHTML과 insertAdjacentHTML을 사용하는 것을 이용하여 공격하는 것이다.
간단하게 어떤 방식으로 이뤄지는지 예시를 보자.
위와같은 TodoList가 있다. 이 항목에 '안녕'이라는 텍스트를 넣어 할 일을 추가하는 방식이다. 하지만 이곳에 일반 텍스트를 넣지않고 아래와 같은 태그를 넣게 되면 다음과 같이 추가된다.
<h1>내가 새로운 제목을 만들거야</h1>
<button>못생긴 버튼을 만들어볼까?</button>
이것이 단순하게 html태그여서 기존 적용되어 있던 css로만 디자인을 망쳤지만, 만약 이것이 스크립트 태그를 사용하여 쿠키를 가져오는 태그이거나 서버로 악성 url을 보낸다면 사용자들과 개발자들에게 돌이킬 수 없는 상황이 만들어질 것이다.
이러한 XSS공격을 막기 위해서는 어떤 예방조치를 해야할까?
방법은 3가지가 있다.
1. 정규표현식 사용 - 특수문자를 입력받지 못하도록 처리
function defenseXSS() {
const text = document.querySelector("input[name=todo]");
const regex = /^[ㄱ-ㅎ|가-힣|a-z|A-Z|0-9| |]+$/;
if (!regex.test(text.value)) {
alert('특수 문자는 입력할 수 없습니다.');
return false;
}
return true;
}
2. 입력값 치환 - 특수문자를 문자열로 치환하기
value = value.replaceAll("<", "<");
value = value.replaceAll(">", ">");
value = value.replaceAll("\\(", "(")
value = value.replaceAll("\\)", ")");
value = value.replaceAll("'", "'");
3. 직접출력 금지 - c:out을 이용하여 그대로 문자열로 출력하도록 하기
<c:out value="${keyword}"/>
불가피하게 HTML을 넣어야할 때는 위와같은 예방코드들을 추가하여 사용자들의 정보를 탈취하거나 악성코드를 심을 수 없도록 방어하자❗️❗️❗️