XSS 공격과 CSRF 공격
XSS (Cross Site Scripting) 공격
정의
- 공격자가 악의적인 JavaScript 코드를 피해자의 웹 페이지에 삽입하여, 피해자의 브라우저에서 실행되도록 만드는 공격
- 흔히 code injection attack이라고도 함
공격 방식
- 예를 들어, 입력값에 대한 충분한 검증 없이 HTML에 그대로 출력할 경우, 공격자가 스크립트를 삽입할 수 있음
- 삽입된 스크립트는 사용자 세션, 쿠키, 로컬스토리지에 저장된 데이터(예: JWT) 등에 접근하여 탈취할 수 있음
방어 대책
- 입력값 검증 및 출력 인코딩: 사용자 입력을 반드시 검증하고, 출력 시 HTML 이스케이프 처리를 적용
- Content Security Policy (CSP) 적용: 스크립트 실행을 제한하여, 신뢰할 수 없는 코드의 실행을 방지
- 정기적인 보안 점검: XSS 취약점을 지속적으로 확인하고 패치
XSS 공격은 JWT뿐만 아니라 페이지 내의 모든 중요한 정보가 노출될 수 있으므로, 위와 같은 기본적인 보안 대책은 반드시 필요
CSRF (Cross Site Request Forgery) 공격
정의
- 공격자가 사용자가 의도하지 않은 요청을 백엔드 서버에 보내게 하여, 피해자인 척 악의적인 동작(정보 수정, 정보 열람 등)을 수행하게 만드는 공격
공격 과정 (예시)
- 공격자는 사용자가 이미지나 링크를 클릭하도록 유도
- 이 클릭 액션은 사용자의 의지와 무관하게 HTTP request를 발생
- 사용자가 이미 로그인되어 있다면, 브라우저는 자동으로 인증 쿠키를 함께 전송하여 서버는 정상적인 요청으로 인식
방어 대책
- CSRF 토큰 적용: 요청마다 서버에서 발급한 토큰을 포함시켜, 유효하지 않은 요청을 차단
- 쿠키의 SameSite 옵션 설정: SameSite=Lax 또는 SameSite=Strict를 적용하여, 외부 요청에 쿠키가 포함되지 않도록 제한
CSRF 공격은 단순히 HTML 태그(img, link 등)만으로도 발생할 수 있기 때문에, 위와 같은 추가 방어 조치는 필수.
JWT 저장 위치: Local Storage vs. Cookie vs. 메모리
Local Storage에 저장
장점
- CSRF 공격에 안전
- Local Storage에 저장된 토큰은 브라우저의 자동 요청에 포함되지 않으므로, CSRF 공격에 취약하지 않음
- 개발자 제어
- 필요 시 JavaScript를 통해 직접 헤더에 토큰을 담아 전송 가능
단점
- XSS 공격에 취약
- 악의적인 스크립트가 주입되면 Local Storage에 접근해 토큰을 탈취할 수 있음
- 지속성
- 브라우저에 영구 저장되어, 탈취 시 장기간 위험에 노출될 수 있음
Cookie에 저장 (HttpOnly 옵션 활용)
장점
- XSS 공격에 강함:
- HttpOnly 옵션이 적용되면 JavaScript에서 쿠키에 접근할 수 없어, XSS 공격에 의한 토큰 탈취 위험이 줄어듦
- 자동 포함
- 브라우저가 HTTP 요청 시 자동으로 쿠키를 포함시켜 편리함
단점
- CSRF 공격에 취약
- 쿠키는 모든 요청에 자동 포함되므로, 공격자가 CSRF 기법으로 피해자의 인증 정보를 도용할 수 있음
- 추가 보안 설정 필요
- CSRF 방어를 위해 SameSite 옵션이나 별도의 CSRF 토큰 적용이 필요하며, 서버와의 협의가 요구됨
메모리(JavaScript 변수)에 저장
장점
- XSS 공격 위험 최소화
- 토큰이 브라우저 메모리에만 존재하므로, 페이지를 새로고침하거나 브라우저를 닫으면 사라져 장기간 노출 위험이 없음
- CSRF에 안전
- 메모리에 저장된 토큰은 자동으로 HTTP 요청에 포함되지 않음
단점
- 휘발성
- 페이지 리프레시나 브라우저 종료 시 토큰이 소실되어, 재인증이나 Refresh Token을 통한 토큰 재발급이 필요함
- 사용자 경험:
- 지속적 인증 상태 유지를 위해 별도의 처리 로직이 필요
Access Token과 Refresh Token 분리 관리 권장 방식
보안성과 사용자 경험을 모두 고려할 때, 가장 권장되는 방식은 Access Token과 Refresh Token을 분리하여 관리하는 것.
Access Token
- 특징: 짧은 유효기간을 가지며, 민감 정보임
- 저장 위치: 메모리(예: JavaScript 변수)에 저장하여, XSS 위험을 최소화
- 보호: 유출되더라도 유효기간이 짧아 피해를 제한할 수 있음
Refresh Token
- 특징: 비교적 긴 유효기간을 가지며, 새로운 Access Token 발급에 사용
- 저장 위치: HttpOnly Cookie에 저장하여, JavaScript에서 접근할 수 없게 함
- 보호: XSS 공격에 대한 보호가 강화되며, CSRF 방어(SameSite 옵션 등) 추가 적용
XSS 공격은 입력값 검증, 출력 인코딩, CSP 적용 등을 통해 방어해야 하며, JWT가 저장된 위치에 따라 보안 위협이 달라짐.
CSRF 공격은 CSRF 토큰 및 SameSite 쿠키 옵션을 활용하여 방어할 수 있음.
JWT 저장 방식에서는 Access Token은 메모리에 저장하여 XSS 위험을 줄이고, Refresh Token은 HttpOnly 쿠키를 통해 CSRF와 XSS 모두에 대한 보안을 강화하는 방식이 보편적이고 안전.