XSS(Cross-Site Scripting)
공격자가 클라이언트 브리우저에 js를 삽입해 실행하는 공격이다. input tag를 통해 또는 url을 통해 js를 적어 클라이언트에서 실행이 가능하다면 사이트에 스크립트를 삽입해 xss공격을 할 수 있다. 공격자는 이를 이용해 사이트의 글로벌 변수값을 가져오거나 또는 그 값을 이용해 API 요청을 보낼 수 있다. 사용자가 글을 읽고, 쓰는 게시판에서 많이 발생 하지만 사용자의 입력 값을 보여주는 곳에서도 발생 한다.
XSS공격은 다음과 같은 종류가 있다.
1. Persistent XSS
지속적인 피해를 입히는 XSS공격이다. 공격자는 XSS취약점이 있는 곳을 파악해 스크립트를 삽입한다. 삽입된 스크립트는 DB에 서장되고, 저장된 스크립트가 있는 게시글 등을 열람한 사용자들은 해당 스크립트가 작동해 쿠키를 탈취 당하거라 리다이렉션 공격을 받을 수 있다. 스크립트가 DB에 저장되기에 지속적인 공격이 가능하다는 의미에서 Persistent XSS라 한다.
2. Reflected XSS
서버 응답에서 발생한다. 만약 응답 메시지에 스크립트가 삽입 되면 서버가 응답을 줄 때 스크립트가 실행 된다. 통상적으로 Reflected XSS는 공격자가 스크립트와 함께 URL을 사용자에게 누르도록 유도하고, URL을 누른 사용자는 악의적인 스크립트가 실행되고 공격을 당한다.
3. DOM based XSS
DOM based XSS는 스크립트가 포함된 URL을 사용자가 요청하게 되어 브라우저를 해석하는 단계에서 발생한다. 악의적인 스크립트로 인해 클라이언트 측 코드가 원래 의도와는 다르게 실행된다. DOM bases XSS는 프래그먼트를 사용하기 때문에 프래그먼트 부분이 서버에 전송되지 않아 서버에서 탐지하기 어렵다. (ex. http://example.com/a/#default=<script>(document.cookie)</script>)
CSRF(Cross Site Request Forgery)
공격자다 다른 사이트에서 API 요청을 통해 공격을 하는 방식이다. API 콜을 할 수 있는 오리진을 서버에서 지정하지 않았다면 CSRF가 가능하다. 이때 공격자가 클라이언트에 저장된 유저 정보를 사용할 수 있다면 개인 정보를 탈취할 수 있다.
사용자 인증을 받은 웹 애플리케이션에서 해당 유저가 원치 않는 동작을 하게 하는 공격 방식이다. 공격자는 링크를 전송하는 등의 방식으로 유저가 자신이 원하는 동작을 하게 만든다. 만약 대상이 일반 유저라면 이메일 주소 변경 등의 공격을 할것이고, 관리자가 대상이면 해당 웹 애플리케이션 전체를 다 탈취할 수 있다.
CSRF는 유저가 악의적인 요청을 하게 속인다. 유저를 대신해 악의적인 요청을 할 수 있게 피해자의 ID와 권한을 탈취한다. 대부분의 브라우저는 요청시 자동으로 일부 정보를 넘긴다. 예를 들어 유저의 세션 쿠키, IP, 등을 넘긴다. 따라서 만약 유저가 어떤 웹 애플리케이션에 인증을 했다면 악의적인 요청인지, 정상적인 요청인지를 구분할 수 없다.
브라우저에서의 유저 정보 저장 방식과 보안
1. localstorage
브라우저 저장소에 저장하는 방식이다. js내 글로벌 변수로 읽기, 쓰기가 가능하다. 따라서 refresh toekn, access token을 저장 하면 XSS취약점을 통해 그 안에 담신 값을 불러오고, 그 값을 이용해 API 요청을 보낼 수 있다.
2. cookie
브라우저 쿠키를 이용하면 HTTP 요청을 보낼 때 마다 자동으로 쿠키가 서버에 전송된다. JS의 글로벌 변수로 읽기, 쓰기가 가능하다.
쿠키안에 세션 id, refresh token, access token을 저장했다면, XSS취약점으로 인해 담긴 값을 불러오거나, API콜을 보내 쿠키에 담긴 값들이 함께 전송되 로그인한 척 공격을 할 수 있다.
쿠키에 세션 id, access token을 저장한다면 CSRF취약점으로 인해 공격자가 유저 권한을 가져올 수 있다.
따라서 쿠키에 refresh token만 저장 하고 새로운 access token을 받아와 인증하는 구조에서는 CSRF를 방어할 수 있다. refresh token으로 access token을 받아 와도 access token을 스크립트에 삽입할 수 없으면 access toekn을 사용해 유저 정보를 가져올 수 없다. 이때 httoOnly쿠키를 적용하면 XSS역시 방어할 수 있다. 하지만 httoOnly 쿠키에 담긴 값 또한 XSS취약점을 사용해 API 콜을 요청하면 유저의 정보를 빼올 수 있다.
따라서 어떤 방식을 사용해도 보안 취약점은 존재 한다. 따라서 클라이언트, 서버에서 추가적인 XSS방어 처리를 해야 한다.
정리
따라서 다음과 같은 방식으로 사용해 로그인을 처리하면 된다.
JWT -> refresh token은 secure httpOnly 쿠키로, access token은 localstorage를 이용해 CSRF와 XSS취약점 공격으로 저장된 유저 정보 읽기를 막는다 -> 하지만 XSS를 통한 API 요청은 막지 못하기 때문에 클라이언트, 서버에 추가적인 보안이 필요 하다.