웹 스토리지(localStorage, sessionStorage)와 보안
웹 스토리지에 개인정보나 로그인 토큰처럼 민감한 데이터를 저장하는 것은 보안상 매우 부적절하며 권장되지 않습니다.
웹 스토리지가 위험한 이유: XSS
가장 큰 이유는 XSS(교차 사이트 스크립팅, Cross-Site Scripting) 공격에 취약하기 때문입니다.
- 자바스크립트로 접근 가능: 웹 스토리지는
window.localStorage.getItem('token')처럼 자바스크립트 코드로 누구나 쉽게 접근할 수 있도록 설계되었습니다. - 공격 시나리오: 만약 웹사이트에 XSS 취약점이 존재한다면, 공격자는 악의적인 스크립트를 웹사이트에 삽입할 수 있습니다.
- 정보 탈취: 이 스크립트는 사용자의 웹 스토리지에 저장된 모든 정보(예: 로그인 토큰, API 키, 개인정보)를 읽어내어 공격자의 서버로 전송할 수 있습니다.
- 결과 (세션 하이재킹): 공격자는 탈취한 토큰을 이용해 사용자인 것처럼 로그인하여 계정을 탈취(세션 하이재킹)할 수 있습니다.
️ 안전한 대안: HttpOnly 쿠키
로그인 상태를 유지하기 위한 세션 토큰이나 **JWT(JSON Web Token)**는 **쿠키(Cookie)**를 사용하되, 반드시 특정 속성을 설정하여 저장해야 합니다.
가장 중요한 속성은 HttpOnly입니다.
- HttpOnly 속성이란? 이 속성이 설정된 쿠키는 오직 서버와 브라우저 간의 통신(HTTP 요청/응답)에만 포함되며, 클라이언트 측의 자바스크립트(
document.cookie)로는 절대 접근하거나 읽을 수 없습니다. - HttpOnly 쿠키를 사용하면, XSS 공격이 성공하여 악성 스크립트가 실행되더라도 공격자는 쿠키에 저장된 토큰을 훔쳐갈 수 없습니다.
안전한 로그인 유지를 위해서는 보통 다음과 같은 속성들을 함께 사용하는 것이 좋습니다.
- HttpOnly: 자바스크립트 접근 차단 (XSS 방어)
- Secure: 오직 HTTPS 연결에서만 쿠키 전송 (중간자 공격 방어)
- SameSite=Strict (또는 Lax): CSRF(교차 사이트 요청 위조) 공격 방어
그럼 웹 스토리지는 언제 사용하나요?
웹 스토리지는 XSS 공격으로 탈취되더라도 큰 문제가 되지 않는 민감하지 않은 정보를 저장할 때 유용합니다.
- 사용자 UI 설정 (예: 다크 모드/라이트 모드 테마)
- 캐시된 비민감성 애플리케이션 데이터 (예: 자주 바뀌지 않는 카테고리 목록)
- 페이지 재방문 시 사용자 편의를 위한 간단한 정보 (예: “오늘 하루 이 팝업 보지 않기”)
강사님의 추가 설명: “보안에 대한 규칙만 제공할 수 있으면 웹스토리지는 괜찮다”에 대한 반박
말씀하신 “보안에 대한 규칙”이라는 것이 아마도 **“XSS(교차 사이트 스크립팅) 공격을 100% 완벽하게 막을 수 있다면”**이라는 전제를 의미하는 것 같습니다.
그 말은 이론적으로는 맞지만, 현실적으로는 매우 위험한 가정입니다.
제가(강사가) 웹 스토리지를 반대하는 이유는 **‘심층 방어(Defense in Depth)‘**라는 보안의 핵심 원칙 때문입니다.
️ “완벽한 방어”라는 위험한 가정
보안은 하나의 방어선에만 의존하지 않습니다.
- 가정: “우리 웹사이트는 XSS 취약점이 절대 없어. 모든 개발자가 완벽하게 사용자 입력을 처리하고, 모든 라이브러리가 안전해. 그러니 웹 스토리지에 토큰을 넣어도 돼.”
- 현실: 현대 웹 애플리케이션은 매우 복잡합니다.
- 내가 작성하지 않은 **수많은 외부 라이브러리(npm 패키지 등)**를 사용합니다.
- 개발자는 실수를 할 수 있습니다. (예:
innerHTML에 사용자 입력을 그대로 삽입) - 새로운 유형의 공격(제로데이)이 발견될 수 있습니다.
단 하나의 XSS 취약점이라도 발견되는 순간, 웹 스토리지에 저장된 모든 정보는 즉시 탈취됩니다. 100번 방어에 성공해도, 1번만 뚫리면 끝입니다.
HttpOnly 쿠키: 뚫려도 지켜주는 2차 방어선
HttpOnly 쿠키를 사용하는 이유는 1차 방어선(XSS 방어)이 뚫렸을 때를 대비한 2차 방어선입니다.
-
웹 스토리지 시나리오 (방어선 1개):
- 공격자가 XSS 취약점을 찾음. (1차 방어 뚫림)
- 악성 스크립트가
localStorage.getItem('token')을 실행. - 게임 끝. 토큰이 탈취됩니다.
-
HttpOnly 쿠키 시나리오 (방어선 2개):
- 공격자가 XSS 취약점을 찾음. (1차 방어 뚫림)
- 악성 스크립트가
document.cookie를 실행. - 안전. 브라우저가 HttpOnly 플래그 때문에 자바스크립트의 접근을 막아버립니다. 토큰을 훔칠 수 없습니다.
보안 전문가는 “만약”이라는 가정에 의존하지 않습니다. **“뚫렸을 때 어떻게 할 것인가?”**를 항상 대비하며, HttpOnly 쿠키는 그 대비책 중 가장 기본적이고 강력한 수단입니다.
혹시 “암호화해서 저장”을 의미하셨나요?
만약 “보안 규칙”이 “웹 스토리지에 저장하기 전에 암호화한다”는 의미였다면, 그것 역시 안전하지 않습니다.
- 암호화를 하려면 암호화 키(Key)가 필요합니다.
- 웹 스토리지의 데이터를 사용하려면 클라이언트(브라우저)에서 복호화(푸는 것)를 해야 합니다.
- 즉, 암호화 키 또는 복호화 로직이 어차피 자바스크립트 코드 안에 존재해야 합니다.
XSS 공격자는 localStorage의 암호화된 토큰을 훔친 뒤, 소스코드에 있는 키나 복호화 함수를 그대로 가져가서 똑같이 풀어버릴 수 있습니다. 이는 금고(웹 스토리지)에 금(토큰)을 넣어두고 금고 바로 옆에 열쇠(암호화 키)를 두는 것과 같습니다.
작성일: 2025-10-29