• JWT, Cookie, XSS, CSRF :: 마이구미
    HTTP 2020. 6. 14. 15:35
    반응형
    이 글은 JWT, Cookie, XSS, CSRF 에 대해 다룬다.
    JWT 와 Cookie 기반 인증 시스템의 차이점에 대한 내용을 기반으로 XSS, CSRF 를 다룰 것이다.
    참고 자료 - https://medium.com/redteam/stealing-jwts-in-localstorage-via-xss-6048d91378a0

     

     

    각 용어에 대한 간략히 설명한 후, 다른 링크로 대체하겠다.

     

    • JWT - JSON Web Token 으로 토큰의 형태이다. (https://en.wikipedia.org/wiki/JSON_Web_Token)
    • Cookie - 사용자 컴퓨터에 방문 기록, 로그인 정보 등과 같은 데이터를 기록할 수 있는 작은 파일 형태를 나타낸다.
    • XSS - Cross Site Scripting 으로 사용자의 정보(쿠키, 세션)를 탈취하는 것이 목적인 공격 기법이다.
    • CSRF - Cross Site Request Forgery 으로 사용자가 자신의 의지와는 무관하게 공격자가 의도한 행위를 하는 공격 기법이다.

     

     

    우선 JWT, Cookie 를 서로 비교해본다.

    각각으로만 본다면, 단순히 형태에 불과하기에 비교하기가 어렵다.

    각각을 이용한 인증 방식에 대한 시스템으로 분류해보자.

     

    쿠키 기반 시스템과 토큰 기반 시스템으로 분류할 수 있다.

    시니어 개발자가 아니라면 대부분 토큰 기반 시스템이 익숙할 것이라 생각한다.

     

    방식의 가장 차이점은 상태의 여부이다.

    쿠키는 stateful 이고, JWT stateless 라고 있다.

    쿠키는 인증 정보를 클라이언트와 서버가 모두 유지하고 있어야한다.

    토큰은 서버에서 발급만 할뿐이고, 클라이언트에 저장된다. (조금 있다가 다룰 XSS, CSRF 와 밀접한 관계가 있다.)

    이를 중점으로 차이점을 접근하면 이해에 더 도움을 줄 것이다.

     

    우선 쿠키 기반 시스템은 다음과 같다.

     

     

    우선 위 그림에서 나타내는 순서는 다음과 같다.

     

    1. 클라이언트에서 사용자 인증을 위해 서버에 요청한다.
    2. 서버는 클라이언트 구분을 위한 session id 와 인증 정보를 DB 와 같은 저장소에 저장한다.
    3. 일반적으로 response 에 set-cookie 에 session id 과 함께 클라이언트에 내려주게 된다.
    4. 클라이언트에서는 쿠키에 session id 를 함께 저장하게 된다.
    5. 필요한 요청마다 session id 와 함께 서버에 요청하게 된다.
    6. 서버는 session id 를 통해 저장소에 접근하여 이를 기반으로 인증을 확인한 후, 결과를 내려준다.

     

    위에서 언급했듯이, 쿠키 기반은 stateful 이다.

    클라이언트와 서버 둘다 인증 정보를 모두 유지하고 있는 상태를 전제하에 진행된다.

    그리고 쿠키는 기본적으로 도메인을 기반으로 설계가 되어있기에, 서로 다른 도메인에서 사용할 수 없다.

     

    토큰 기반 시스템은 다음과 같다.

     

     

    우선 위 그림에서 나타내는 순서는 다음과 같다.

     

    1. 클라이언트에서 사용자 인증을 위해 서버에 요청한다.
    2. 서버는 토큰을 발급하여 클라이언트에 내려준다.
    3. 클라이언트는 토큰을 localStorage, sessionStorage, Cookie 와 같은 장소에 저장한다.
    4. 필요한 요청마다, 토큰과 함께 서버에 요청한다.
    5. 서버는 토큰 검사를 통해 인증을 확인하고, 결과를 내려준다.

     

    위에서 언급했듯이, 토큰 기반은 stateless 이다.

    서버는 토큰을 발급만 하고, 클라이언트에서 저장된다.

    만약 사용자가 로그아웃한다면, 클라이언트에 저장된 토큰만 소멸될 뿐, 서버와의 상호작용은 일어나지 않는다.

    그리고 쿠키와 달리 도메인의 영향을 받지 않는다.

     

    위에서 언급한 "토큰은 서버에서 발급만 할뿐이고, 클라이언트에 저장된다." 은 3번을 의미한다.

    XSS, CSRF 공격에 대한 취약점과의 관계가 연결된다.

     

    토큰을 만약 localStorage 에 저장한다면, XSS 공격 취약점이 생긴다.

    알다시피 localStorage 는 스크립트 실행으로 가져올 수 있기 때문이다.

     

    <script>alert(localStorage.getItem(‘key’))</script>

     

    사실 쿠키에 저장해도 스크립트를 통해 가져올 수 있게 된다.

     

    <script>alert(document.cookie)</script>

     

    쿠키는 이 행위를 막을 수 있는 속성이 존재한다.

    우리는 httpOnly, secure 속성을 활용할 수 있다. (https://developer.mozilla.org/ko/docs/Web/HTTP/Cookies)

    httpOnly 속성은 document.cookie 와 같은 스크립트 실행을 막을 수 있다.

    secure 속성은 https 요청일 때만 전송하게 된다.

    이를 활용한 예는 구글사이트에서 확인해볼 수 있다.

     

     

    스크립트 실행으로 볼 수 있는 쿠키값들은 위와 같다.

    모든 쿠키를 한번 확인해보자.

     

     

    보다시피 httpOnly 값이 체크된 데이터들은 위 콘솔에 찍히지 않았다는 것을 확인할 수 있다.

    이렇게 쿠키는 기본적으로 XSS 공격을 방어할 수 있게 된다.

     

    하지만 토큰을 쿠키에 저장할 경우에는 CSRF 공격에 취약하게 된다.

    토큰이 쿠키에 기본적으로 저장되어있기에, 탈취는 할 수 없겠지만 인증된 사용자의 행위는 할 수 있게 된다.

    예를 들어, 자동으로 글을 작성하는 스크립트를 실행하는 것이다.

    자동으로 댓글을 쓰게 하는 행위는 정보를 탈취하는 것이 아니라 단순히 사용자 행위를 하는 것이다.

    이를 위해 Referer 체크, CSRF 토큰 사용 등 방어책을 마련해야한다.

     

    결론적으로 토큰은 localStorage 가 아닌 쿠키에 담아 사용하는 것이 더 일반적이고 올바른 방식이라고한다.

    반응형

    댓글

Designed by Tistory.