지난 포스트에서 JWT가 무엇인지, 다른 인증 방식은 무엇인지, 각각의 장단점은 무엇인지 알아보았다.
이번 포스트에서는 토큰 관리를 위해 고려해야 하는 보안 이슈들을 공부해 보았다.
XSS 공격
아마 조금이라도 토큰관리에 대해서 관심을 가졌다면 가장 익숙한 단어일 것이다.
보안에 대해서 문외한이지만 내가 조사한 내용을 적어보자면 다음과 같다.
XSS 공격이란?
XSS는 Cross Site Scripting의 약자로, 직역하면 사이트 간 스크립팅이다.
가장 기초적이고 단순하지만 그만큼 강력하고 계속해서 문제가 발생하는 보안 이슈라고 한다.
이 공격은 쉽게 말해서 해커가 보안이 취약한 사이트에 악의적인 스크립트를 심어 사용자가 이 스크립트를 읽도록 유도하여 사용자의 정보를 빼았는 공격 기법이다.
말로만 보면 무슨 말인지 이해하기 어려우니 예제를 통해서 이해해보자
XSS 예제
코드몽키 군이 만든 어느 커뮤니티 사이트가 있다.
코드몽키 군은 사용자가 게시물 제목과 내용을 입력하면 다른 사용자가 읽을 수 있는 게시물을 생성할 수 있다.
그리고 해당 게시물은 DB에 저장해 관리한다.
만약, 코드몽키 군이 보안에 대해 관심이 없어 클라이언트 측 입력 필터나, 서버 쪽 필터를 고려하지 않았다면 어떻게 될까?
<script> alert("넌 망했어")</script>
바로 이와 같은 자바스크립트 스크립트를 게시물에 입력을 할 수 있게 된다..!
예시에는 귀여운 alert만 넣었지만 만약 사용자의 쿠키와 로컬스토리지에 저장된 중요한 정보를 빼돌리는 코드라면 어떻게 될까..?☠️☠️☠️
XSS 공격이 들어올 경우?
예제를 보면 알 수 있듯이 XSS 공격 스크립트로 얻을 수 있는 사용자 정보들은 다음과 같다.
localStorage, SessionStorage, Cookie, 등등
쿠키 인증방식이나 토큰 값들을 localStorage에 저장했다면 모든 정보가 다 털릴 수 있다..!
중요한 정보를 이와 같은 장소에 저장하면 위험하다고 하는 이유가 바로 여기 있었다.
CSRF
다음은 CSRF에 대해서 간단히 알아보자.
CSRF 공격이란?
CSRF는 Cross Site Request Forgery의 약자로, 직역하면 사이트 간 요청 위조이다.
XSS 공격에서는 클라이언트의 중요 정보를 탈취하는 목적과, 해당 사이트에서만 국한된 공격임을 알 수 있었다.
그에 반해 CSRF는 쿠키가 자동으로 포함된다는 특성을 활용하여 다른 외부 사이트에서 사용자가 권한을 가진 사이트에 특정 요청을 보내는 공격이다!
이번에도 예제를 통해 CSRF 공격이 어떤 것인지 알아보자.
CSRF 예제
XSS 공격으로 직장에서 해고된 코드몽키는 퇴직금으로 사업을 시작했다.
코드몽키씨는 카카오페이를 뛰어넘을 은행 사이트를 개발하고 배포하였다.
코드몽키씨는 지난 실패를 기점으로 XSS 공격을 막기 위해 정말 열심히 사용자의 입력에 대한 필터를 적용하였다.
하지만 코드몽키씨는 하나를 알면 하나만 아는 사람이었다..
<img src="http://YOU/ARE/FxxKED" width="0" height="0" />
악성 스팸 메일을 통해 악성 링크를 클릭한 유저들은 다음의 스크립트가 저장된 악성 사이트에 접속하게 되었고,
html을 파싱 하며 자동으로 img 태그의 src 요청을 보내게 된다.
이때 해커가 src에 은행 계좌이체 api를 설정하게 된다면 어떻게 될까?☠️🤡☠️
이미 코드몽키씨의 은행 사이트에 인증을 하여 쿠키에 인증토큰이 저장되어 있는 유저들의 돈이 해커에게 탈탈 털리게 되는 것이다..
세션 하이재킹
이 부분은 다음에 추가적으로 조사할 예정이다.
간단히 말해 HTTP 요청이 진행되는 중 네트워크 패킷이 해커에 의해 유출되는 공격 방식이다.
토큰을 어떻게 관리해야 할까?
토큰을 관리하는 데에 있어 고려해야 할 가장 중요한 세 가지 보안 이슈를 알아보았다.
우리는 어떻게 해야 다음과 같은 악의적인 보안 공격에 보다 안전할 수 있을까?
해결책
다행히도, XSS와 CSRF에 대한 대응책은 다음과 같은 방법으로 어느 정도 막을 수 있다고 한다.
입력 검증
XSS는 입력 검증이 취약한 페이지를 대상으로 악의적인 스크립트를 삽입하여 발생한다.
따라서, <>와 같이 스크립트를 출력할 수 있는 위험한 문자에 대한 필터링이나 라이브러리 등을 통해 입력 부분에서 필터링을 거치는 것이 좋을 것 같다.
httpOnly
사람은 누구나 실수할 수 있다.
XSS공격이 들어오게 되었을 때 피해를 최소화할 수 있는 방법은 무엇일까?
바로, httpOnly 속성이다!
httpOnly는 쿠키에 적용할 수 있는 속성으로, 서버에서 토큰을 발급할 때 쿠키에 담아 httpOnly 속성을 적용하게 되면 클라이언트에서 스크립트를 통해 토큰을 임의로 조작, 탈취할 수 없게 된다.
따라서, 토큰을 따로 추출할 부분이 없다면 XSS 공격을 대비하여 고려하기 좋은 방책인 것 같다!
LocalStorage에 저장하기?
CSRF 공격은 사용자가 인증한 페이지로 요청을 보낼 때 외부 도메인에서 하는 요청이라도 쿠키가 자동으로 첨부되어서 보내지는 특성을 활용하는 공격이다.
그러면 쿠키를 사용하지 않고, localStorage를 활용하면 CSRF 공격은 충분히 방어를 할 수 있다.
하지만 xss 공격에 대해서 완전히 방어하기는 어려운 부분이 많기에 많이 사용되지 않는 방법이라고 한다.
HTTP Header에 토큰 넣기?
CSRF 공격을 방지하기 위해 서버로부터 받은 토큰을 localStorage와 같은 곳에 저장하고,
필요한 요청에 한에서만 Header에 토큰을 첨부해 보낼 수 있다.
이 방식은 확실히 CSRF에 대해서는 예방할 수 있지만 다른 저장소를 사용하기에 XSS 공격에 대한 예방이 필요한 점, httpOnly를 사용할 수 없다는 점과 같은 문제점이 존재한다.
SameSite
httpOnly로 클라이언트의 쿠키 탈취를 막을 수 있었던 것처럼 SameSite 속성을 통해 외부 사이트에서의 요청을 막을 수 있다.
SameSite 속성은 클라이언트의 도메인과 요청받는 도메인이 같아야만 쿠키를 전송하기 때문에 CSRF에 대한 방지에 도움이 된다.
HTTPS / Secure
네트워크 패킷이 유출되는 것을 막기 위해 HTTPS는 큰 강점을 가질 수 있다.
HTTPS는 HTTP와 달리 클라이언트와 서버 간의 데이터 전송을 암호화해 무결성을 보장해 주는 프로토콜이다.
Secure 속성은 쿠키의 속성으로 쿠키를 HTTPS로만 전송하도록 설정할 수 있는 속성이다.
HTTPS와 Secure 속성을 사용하면 네트워크 패킷 유출도 막을 수 있고 쿠키의 안정성을 보장해 줄 수 있다!
결론은?
이 글을 정리하며 느낀 결론은 다음과 같다.
access token : 전역 변수에 저장 (메모리를 활용해 외부로부터 안전하게 보관)
refresh token : 쿠키에 저장 (쿠키에는 Secure, SameSite(재발급 api에서만 사용), HttpOnly 적용)
HTTPS 프로토콜 사용
이렇게 하면 XSS 공격과 CSRF 공격, 네트워크 패킷 유출에 대해 강력한 보안 설정을 구축할 수 있을 것으로 생각된다.
또한 프론트 단에서 RT를 따로 관리해 줄 필요가 없어지기에 안정성과 개발 상의 편리함도 늘어날 것으로 판단된다.
'React' 카테고리의 다른 글
| [React] onKeyDown이 두 번 적용되는 현상을 분석해보자 (5) | 2025.07.29 |
|---|---|
| [React] firebase + github action CI/CD 파이프라인 구축 (1) | 2025.03.19 |
| [React] JWT 이해하기 (3) | 2025.03.19 |