CSRF(Cross Site Request Forgery)
CSRF는 여러가지 보안 취약점 공격 중 하나이다
다른 사이트(cross-site)에서 유저가 보내는 요청(request)을 조작(forgery)하는 것
ex) 이메일에 첨부된 링크를 누르면 내 은행 계좌의 돈이 빠져나감
해커가 직접 데이터를 접근할 수는 없다
→ 다른 사이트이기에 response에 직접 접근할 수는 없음
(해커가) CSRF 공격을 하기 위한 조건
* 쿠키를 사용한 로그인
- 유저가 로그인했을 때, 쿠키로 어떤 유저인지 알 수 있어야 함
* 예측할 수 있는 요청/ 파라미터를 가지고 있어야 함
- request에 해커가 모를 수 있는 정보가 담겨 있으면 안됨
(해커로 빙의해) Get 요청으로 CSRF 공격한다면?
ex) 고객 A가 계좌이체로 돈을 전송하려고 하는데 해커 B가 CSRF 공격한다고 가정
Get https://은행.com/transfer?account_number=고객A&amount=100만원
이 request를 해커가 중간에 가로채서,
Get https://은행.com/transfer?account_number=해커B&amount=100만원
로 request를 바꿈
(해커로 빙의해) Post 요청으로 CSRF 공격
ex) 해커가 가짜 웹사이트를 통해서 일종의 스크립트 공격을 하도록 하여,
고객이 페이지 클릭 시 숨겨진 폼이 동작하여 post 요청을 자동으로 보내 비밀번호를(해커가 원하는 비번) 바꾸게 함
// post는 body(payload)에 정보를 담아서 보냄
post http://은행.com/password/change
body: {password: 해커가 바꾼 비번}
CSRF를 막는 방법
* CSRF 토큰 사용
- 서버측에서 CSRF 공격에 보호하기 위한 문자열을 유저의 브라우저와 웹 앱에만 제공
→ 이 조합으로 생성된 요청에만 요청을 완료해 주는 것
* same-site cookie 사용하기
→ 같은 도메인에서만 세션/쿠키를 사용할 수 있도록 함
Token(토큰)
Token-based Authentication(토큰 기반 인증)
이전에 배운 세션 기반 인증
은 다음과 같았다
→ 서버(혹은 DB)에 유저 정보를 담는 방식
→ 매 요청 시마다 서버가 부담을 가져야 함
이 부담을 클라이언트에게 주는 것이 토큰
클라이언트에서 인증 정보를 보관하는 방식
→ 토큰은 유저 정보를 암호화한 상태로 담을 수 있고, 암호화했기 때문에 클라이언트에 담아도 위험하지 않다
대표적인 토큰 기반 인증: JWT(Json Web Token)
JWT(Json Web Token)
Json 포맷으로 사용자에 대한 속성을 저장하는 웹 토큰
사용하는 토큰의 종류는 크게 2가지가 있다
1. Access Token
- 보호된 정보들에 접근할 수 있는 권한 부여에 사용
2. Refresh Token
- Access Token이 만료되면 이 토큰을 이용하여 새로운 Access Token을 발급받음
클라이언트가 처음 인증 시(로그인 시), Access, Refresh Token 2가지를 다 받는다
→ 실질적으로 권한
을 받는데 사용하는 것은 Access Token
→ 허나, Access Token이 탈취 시 발생할 문제점을 대비하여 짧은 유효 기간
을 부여
→ 만료 시마다 Refresh Token을 이용하여 재발급 받도록 함
물론, Refresh Token도 탈취당하면 큰 일이기 때문에, 정보를 중요시하는 웹사이트들은 Refresh Token을 사용 안 하기도 한다(Access token만 사용)
JWT의 구조
점 .
으로 나누어진 3부분으로 구분됨
JWT는 권한 부여
에 매우 유용하다
aaaaaa.bbbbbb.cccccc
header payload signature 부분
1. header
- 어떤 종류의 토큰인지?
- 어떤 알고리즘으로 암호화?인지 적혀 있음
ex) {“alg”: “HS256”, “typ”:”JWT”} // JSON 형태의 객체
→ base64 방식으로 인코딩(암호화시)
2. payload
- 유저의 정보가 담김
- 권한과 관련(어떤 정보에 접근 가능?)
- 기타 필요한 정보(유저 이름 등)
→ 암호화가 되지만 그래도 민감한 정보는 담지 않는 게 좋다
ex) {
"sub": "someInformation",
"name": "phillip",
"iat": 151623391
} // JSON 형태의 객체
→ base64로 인코딩(암호화)
3. signature
- header, payload를 base64인코딩한 값에 salt값(원하는 비밀키)을 조합하여 암호화시킨 값
ex) HMAC SHA256 알고리즘을 사용한 signature 생성 예
HMACSHA256(base64UrlEncode(header) + '.' + base64UrlEncode(payload), secret);
토큰 기반 인증 절차
1. 클라이언트가 서버에 로그인 request(with 아이디/비밀번호)
2. 서버는 아이디/비번 일치 확인 후, 암호화된 토큰(access/refresh)을 생성
3. 이 토큰을 클라이언트에 보내주면, 클라이언트는 토큰을 저장
- 저장 위치는 다양하게 가능(로컬 스토리지, 쿠키, 리액트의 스테이트 등)
4. 클라이언트가 HTTP 헤더(authorization 헤더)에 토큰을 담아 요청(request)
- bearer authentication을 이용함
참고: https://learning.postman.com/docs/sending-requests/authorization/#bearer-token
5. 서버는 받은 토큰을 해독하여, 토큰이 맞으면 클라이언트의 요청을 처리한 후 응답(response)
토큰 기반 인증의 장점
1. Statelessness & Scalability(무상태성 유지 & 확장성 용이)
- 서버가 클라이언트 정보를 저장할 필요없으니깐(서버 입장에서 무상태성 유지)
- 서버를 여러 개 가지고 있는 서비스라면 더욱 유용(확장성 용이)
→ 같은 토큰으로 여러 서버에서 인증 가능
2. 안전성
- 암호화된 토큰을 사용하고, 암호화 키를 외부에 노출하지 않으므로
3. 어디서나 생성 가능
- 꼭, 토큰을 확인하는 서버가 토큰을 생성할 필요x
- 토큰 생성은 토큰 생성용 서버를 만들거나 다른 회사꺼 써도 된다
4. 권한 부여에 용이
- 권한과 관련해 토큰의 payload에 어떤 정보에 접근 가능한지 정하면 됨
추가적인 내용 및 의문점 정리
- 비대칭키 암호화 방식에서
private key로 암호화한 데이터는 public key로는 복호화가 불가능하지는 않지만
→ 실제로 사용하지는 않는다(딱 봐도 보안상 위험) - 해시 함수
극히 드물게 다른 입력값인데도 해시된 값이 같은 경우가 발생할 수 있음
→ 이러한 중복이 적게 발생할 수록 좋은 해시 함수임 - 쿠키
mdn의 "세션 쿠키" 설명과는 다르게, 현대의 브라우저는 쿠키를 지우지 않는 것이 기본 옵션으로 되어 있음 - sameSite 옵션이
none
이면 항상 secure 옵션도true
여야 한다(https 프로토콜 사용)
sameSite = ‘none’, secure=true
same-origin과 same site의 차이?
동일 출처(same-origin) 조건이랑 sameSite 조건은 미묘하게 차이가 존재 한다
다음 문서를 참고할 것
https://web.dev/same-site-same-origin/#same-site-cross-site
Understanding "same-site" and "same-origin"
"same-site" and "same-origin" are frequently cited but often misunderstood terms. This article helps you understand what they are and how they are different.
web.dev
3rd-party cookie
- 써드파티 쿠키를 사용하는 경우?
ex) 외부에서 이미지를 가져오는 태그 같은 것을 사용하는 경우
→ 원본 사이트에서 태그를 통해서 외부 사이트로 요청을 보내서 데이터를 가져옴
<href> <img> 태그를 사용하는 경우?
CSRF 공격과 이를 막는 쿠키의 sameSite 옵션
- CSRF 공격
간단하게 예시로 보면,피싱사이트
에서 특정 버튼 클릭 유도해서 임의로 get, post 요청 등을 클라이언트가 보내도록 만드는(변조된 http 요청) 그런 것
→ CSRF 공격을 막는 가장 중요한 포인트는 쿠키의 sameSite
옵션이다
Session 기반 인증 vs. Token 기반 인증의 가장 큰 차이점
어디에 인증 정보를 저장하는가?(전자는 서버, 후자는 클라이언트)
어느 인증 방식이 더 안전하냐는 따지기 힘들다(안전성은 비슷함)
- JWT의 구조
구조에서 Payload 부분에비밀번호
같은민감정보
는 넣지 않는게 바람직하다(암호화는 되지만 혹시나)
'SE Bootcamp 내용 정리' 카테고리의 다른 글
컴퓨터 공학 - 기초 (0) | 2021.11.26 |
---|---|
인증/보안 - OAuth 인증 구현 (0) | 2021.11.26 |
인증/보안 - session 기반 인증 구현하기 실습 (0) | 2021.11.25 |
인증/보안 - 기초 1: HTTPS, Hashing, Cookie, Session (0) | 2021.11.24 |
데이터베이스 - MVC 패턴 연습 (0) | 2021.11.19 |