XSS (Cross-Site Scripting) 이란?
가장 널리 알려진 웹 보안 취약점 중 하나입니다.
악의적인 사용자가 공격하려는 사이트에 악성 스크립트를 삽입할 수 있는 보안 취약점입니다.
XSS를 통해 악성 코드를 제어하는 사이트로 리다이렉트 하거나, 사용자의 쿠키를 탈취하여 세션 하이재킹 공격을 할 수 있습니다.
대표적인 공격 방식은 다음과 같습니다.
- Stored XSS
- Reflected XSS
- DOM Based XSS
Stored XSS
저장형 XSS 공격은 보안이 취약한 서버에 악의적인 사용자가 악성 스크립트를 저장함으로써 발생합니다. 비정상적인 방법이 아니라 서버에서 제공하는 게시판, 사용자 프로필에 악의적으로 동작하는 스크립트가 그대로 저장된 후 클라이언트의 브라우저로 전달되어 문제가 발생합니다.
Stored XSS 공격 시나리오
1. 해커가 게시물 등록 폼에서 악의적인 코드를 입력합니다.
2. 서버의 DB에 스크립트가 저장됩니다.
3. 사용자가 게시물을 읽으면 해당 스크립트가 HTML 에 주입된 상태로 렌더링됩니다.
4. 스크립트가 실행되어 공격이 실행됩니다.
Stored XSS 공격 코드
다음 악성 스크립트 코드가 삽입된 게시물을 열람하면 사용자의 introduction 이 PUT 요청으로 인해 의도치 않게 변경됩니다.
</textarea>
<script id="worm">
alert("님 해킹 당함.");
window.onload = function () {
var updatedUser = {
introduction: "님 해킹 당함."
};
var xhr = new XMLHttpRequest();
xhr.open("PUT", "/editUser", true);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(JSON.stringify(updatedUser));
};
</script>
Stored XSS 공격 시연
1. 유저의 이름을 클릭하면 해당 유저의 소개글을 볼 수 있는 아주 간단한 어플리케이션 입니다.
2. 해커가 자신의 소개글에 악성 스크립트를 저장합니다.
3. joshoangtien 이라는 유저는 처음에 I'm Fairy 라는 소개글을 가지고 있었습니다.
이 유저는 admin 이라는 해커가 악성스크립트를 심어놓은 자기소개 글을 열람하게됩니다.
글을 열람할때 악성 코드가 실행되어 joshoangtien 유저의 소개글이 변경됩니다.
Stored XSS 방어
그럼 어떻게 방어해야할까요?
1. 문자열 필터링
XSS 공격은 스크립트를 삽입하는 방식으로 발생합니다. 따라서 기본적으로 스크립트 태그를 사용하게 됩니다.
그러므로 스크립트 태그에 자주 사용되는 < , > 과 같은 문자를 필터링 해주는 방법으로 방어할 수 있습니다.
예를 들어 <script> 의 < 은 동일한 의미의 HTML 문자 < 로, > 는 > 로 변경됩니다.
이렇게 하면 사용자에게는 <script> 로 보이지만, HTML 문서에는 <script>로 나타나고 브라우저에서 일반 문자로 인식되어 스크립트가 실행되지 않습니다.
필터링 방어 코드
var newIntroduction = req.body.introduction;
newIntroduction = newIntroduction.replace(/&/g, "&");
newIntroduction = newIntroduction.replace(/</g, "<");
newIntroduction = newIntroduction.replace(/>/g, ">");
newIntroduction = newIntroduction.replace(/"/g, """);
newIntroduction = newIntroduction.replace(/'/g, "'");
적용 예시
2. CSP (Content-Security Policy)
CSP 는 신뢰할 수 있는 출처의 스크립트만 실행하는 정책입니다.
예를 들어 다음과 같은 코드는 same-origin 과 https://apis.google.com 로 부터 로드 되는 코드만 실행한다는 의미를 가집니다.
Content-Security-Policy: script-src 'self' https://apis.google.com
CSP 방어 코드
fs.readFile("resources/viewUser.html", function (err, html) {
res.writeHead(200, {
"Content-Type": "text/html",
"Content-security-policy": "default-src 'self'",
});
html = html.toString();
html = html.replace("{{username}}", currentUser.username);
html = html.replace("{{introduction}}", currentUser.introduction);
return res.end(html);
});
적용 예시
인라인 스크립트 코드는 실행이 되지 않는 것을 볼 수 있습니다.
Test Code Repo
https://github.com/joshoangtien/DemoStoredXSS
참고자료
1. https://junhyunny.github.io/information/security/spring-mvc/reflected-cross-site-scripting/
2. https://www.youtube.com/watch?v=bSGqBoZd8WM
3. https://tecoble.techcourse.co.kr/post/2021-04-26-cross-site-scripting/
4. https://itchallenger.tistory.com/857
5. https://webstone.tistory.com/98
6. https://github.com/joshoangtien/DemoStoredXSS
'CS > 네트워크 & 웹' 카테고리의 다른 글
CSRF (Cross-Site Request Forgery) 공격과 방어 (0) | 2023.04.23 |
---|---|
DOM 기반(DOM based) XSS(Cross-Site Scripting) 공격과 방어 (0) | 2023.04.22 |
반사형(Reflected) XSS(Cross-Site Scripting) 공격과 방어 (2) | 2023.04.13 |
토큰을 어디에 저장해야할까요? (4) | 2023.04.13 |
Transfer-Encoding: Chunked (0) | 2023.04.11 |