로그인기능을 구현할때 쿠키사용시에는 보안관련해서 secure, httponly, csrf.disable, samesite=strict 등 기본 설정이 필요한데
이를위해서 기존에 들었던 XSS와 CSRF가 무엇인지 제대로 공부하게되었다.
먼저 세션기반(쿠키사용)으로 관리할지 JWT 토큰기반으로 관리할지 고민하다가 세션기반의 경우는 서버가 직접관리하면서도 확장성(여러 서버가 생긴다면)이를 통합해야하는 개념과 서버에 과부화가 걸릴수도있는 문제등을 생각했을때 해보고싶은 경험도 중요했지만 이부분은 프리티어 기준으로 너무 신경쓰다보면 꼬일거같아서 과부화와 확장성을위해 좀더 편하게 관리하기위해 JWT 기반으로 사용하기로했다.
JWT를 사용한다면 보통 access token과 refresh token을 사용하게 되는데, 이렇게 사용하는 이유과 결국 물리적으로 해당 토큰을 탈취하게된다면 무한정으로 리소스를 보는데 사용할수있기때문에 access token의 만료기간을 짧게 가져가고 refresh token은 길게 가져가서 주기적으로 업데이트를 하는 경우이다. 하지만 refresh token마져도 탈취가능하다면 access token만 탈취했을때보다 더 위험한경우라 만약 access token과 refresh token을 사용한다면 만료시간을 짧게 가져가는 access token은 탈취가 어느정도 가능할지라도 refresh token만은 탈취되지 않도록해야한다. 이를 위해서 refresh token의 경우는 물리적으로 탈취하지못하도록 httponly 를 통한 쿠키방식으로 사용하기로 결정하게되었다.
이를위해 자바스프링 코드는 응답에 대하여 다음과 같이 설정하게 되는데 각각의 메서드가 무엇을 의미하는지를 알아야했고 이를 통해 XSS와 CSRF를 방지하는거에 대한 고민을 하게 된것이다.
ResponseCookie jwtCookie = ResponseCookie.from("jwtToken", jwt)
.httpOnly(true) // ✅ JavaScript에서 접근 불가능
.secure(true) // ✅ HTTPS에서만 전송
.sameSite("Strict") // ✅ CSRF 방지
.path("/")
.maxAge(3600) // ✅ 만료 시간 설정
.build();
response.addHeader(HttpHeaders.SET_COOKIE, jwtCookie.toString()
Secure
가장먼저 httpOnly와 secure부터 보면 좋을게 이전 글에도 설명한부분 http 와 https차이에 대해서 무엇인지 설명하였는데, secure의 경우는 https의 경우에만 쿠키를 담아 요청 응답할수있도록 하는것이고 이에 대한 이유는 이전글을 보면 알수있다 http의경우는 전송중간에 탈취하게되면 데이터가 암호화되어있지않기 때문에 따로 복호화없이도 이러한 정보들을 사용할수있게 되기때문인데 https인경우는 SSL/TLS handshake가 이루워지기때문에 데이터가 암호화되고 복호화과정이 필요하기때문에 중간에 탈취해도 데이터를 볼수없기때문에 설정하는 것이다.
httpOnly
하지만 전송 중간에 탈취하는게 아닌 물리적인 방법으로 쿠키나 토큰을 탈취한다면 해당 쿠키와 토큰을 이용하여 서버정보에 요청하여 가져갈수있게 된다 따라서 이러한 물리적인 방법으로 탈튀하지못하도록 (프로그래밍 언어를 통한 접근) http통신할때만 요청에 해당 쿠키값이 포함되어 보내지도록 하는것이다. 이는 다음에 설명할 XSS 방어중 한 방법이다. 물리적으로 코드를 통해 탈취할수 없게 하기위해 쓰는 메서드이다.
sameSite
이제 CSRF방어를 위한 설정에 대한 메서드를 알아보자. 아래에 좀더 설명하겠지만 CSRF라는 말은 요청을 위조해서 탈취하는 방법인데 예를들어 악성사이트에서 특정 사이트에 계좌이체를 요청하는 코드를 넣었다고 치자, 그리고 해당 사이트는 쿠키를 통해 인가를 하고있다면, 아무설정없이도 요청하는 코드만 있으면 자동으로 쿠키값으로 계좌이체 요청이 성공하게 된다. httpOnly더라도 samesite 가 none이라면 자동으로 요청이 가능하다는것이다. 따라서 이를 막기위해 samesite라는 부분을 strict으로하여 자동으로 쿠키를 보내주는게아니라 같은 도메인에서 요청일때만 요청하도록한다. 그런데 CORS환경의 서비스일경우, 즉 우리가 백엔드도메인과 프론트도메인이 각각 다른환경에서 api를 요청한다면 동일한 도메인이 아니기때문에 strict으로 하면 쿠키를 주거나 받을수없다. 어쩔수없이 외부 api에서 서버로 요청해서 쓰게해야한다면 samesite를 none으로해야하는데 이때는 그럼 CSRF 토큰을 사용해서 요청할때 사용하도록하고 만약 CSRF토큰이없다면 서버쪽에서 이를 forbidden처리하도록 하는것이다. (근데 결국 CSRF도 토큰이니, XSS에 취약한거아닌가? 거기다가 set-cookie라하면 CSRF자체 취약도되는거고..), 결론적으론 samesite는 None 설정, Secure를 true로 해줘야 실제 배포환경에서 쿠키를 담아서 요청할수있다.
만약 추후에 네이티브코드상에서 요청이 필요한순간이있을때 다시 테스트해봐야할거같다.
참고할점은 localhost일 경우는 Secure를 true로 해주어도 http인곳에서도 쿠키를 담아 보내지게된다.
XSS(Cross Site Scripting)
그래서 XSS는 뭔데? 라고한다면 우리가 토큰값을 가져올때 document.cookie라던가 localStorage.getItem() 과같은 코드를 입력해서 가져올수있게 해놨다. 그렇다면 해킹하는 입장에서도 해당 코드만 주입해줄수만있다면 탈취가 가능하다는 얘기인데 이를 방지하고자 HttpOnly를 쓰게되는것이다. 그렇게하면 쿠키에 접근하더래도 아무값도 볼수없다. 하지만 access token의 경우는 쿠키가아닌 storage에 담아서 사용하기때문에 탈취 위험은 있긴하지만 이를 최소화하기위해 만료일을 짧게 두는게 전략인것이다.
CSRF(Cross Site Request Forgey)
CSRF는 뭔데? 라고한다면 만약 쿠키값을 자동으로 api요청할때 보내줄수만있다면 다른 도메인에서 해당 api를 요청하기만하면된다.
즉 다른 도메인에서 해당 api를 호출하게만들어서 정보를 탈취하는건데 이때 따로 cookie값이나 토큰을 탈취할필요없이 api만 요청하면 자동으로 쿠키의 경우는 요청에 들어가지니 그런점을 이용한 해킹방법이다. 이를 막기위해서 사용하는것이 sameSite 값을 조절하는것이다.
strict으로 할 경우 같은 도메인에서의 요청이여야지만 쿠키값이 들어가지도록 설정해주는것이고 Lax는 Get요청및 링크 태그<a> 같은곳에서 요청할때만 가능하도록 해주는거기때문에 보통 다른사이트에서 테스트요청을 해야할때 사용한다고한다. 단 POST, PUT, DELETE같은 상태변화 요청에는 쿠키가 자동으로 포함될수없는 것이다.
'공부 > CS' 카테고리의 다른 글
Https 도입과정 DNS 구조 이해(브라우저에 도메인 입력시 과정) (0) | 2025.01.28 |
---|---|
Http통신 데이터 형식(바이너리, base64) form-data사용하는이유 (3) | 2024.10.16 |
[CS] 웹팩(webpack), 바벨(babel) (0) | 2023.01.12 |
[CS] 웹 성능최적화 (2), Lighthouse (0) | 2023.01.04 |
[CS] 웹 성능최적화 (1) (1) | 2023.01.03 |