CSRF 공격

사이트 간 요청 위조(Cross-site Request Forgery, CSRF) 공격 은 사용자가 자신의 의지와 상관없이 공격자가 의도한 행위를 특정 웹 사이트에 요청하도록 하는 것을 의미함.

예를 들어, 특정 사용자가 서비스에서 로그인을 수행하고 서버는 해당 사용자의 대한 세션 ID 를 Set-Cookie 헤더에 담아서 응답함. 그리고, 클라이언트는 쿠키를 저장하고 요청마다 자동으로 전달함.

이러한 사용자를 대상으로 공격자는 악성 스크립트가 담긴 페이지에 접속하도록 유도함. 유도하는 방법은 다양한데, 악성 스크립트가 포함된 메일이나 게시글을 작성하거나, 악성 스크립트가 포함된 사이트 접속 링크를 전달하는 것이 대표적임.

사용자가 악성 스크립트가 포함된 페이지에 접속하게 되면 악성 스크립트가 실행됨. 이 스크립트는 사용자의 의도와 상관없는 특정한 요청(결제, 비밀번호 변경) 을 공격 대상 서버로 보내도록 구현이 되어 있음. 해당 요청은 브라우저에 의해서 자동으로 쿠키에 저장된 세션 ID 가 함께 전달됨.

예를 들어, 공격자가 만든 사이트 내부에는 다음과 같은 태그가 존재할 수 있음.

<img src="https://example.com/member/changePassword?newValue=1234"/>

공격자 사이트에 방문한 사용자는 자신의 의지와 무관하게 img 태그로 인해 세션 ID 가 포함된 쿠키와 함께 비밀번호 변경 요청을 서비스가 구동중인 서버로 전달함.

방어 방법

교차 출처인 상황에서 요청을 막는 방식으로 CSRF 를 방어할 수 있음.

  1. Referer 요청 헤더 사용

    Referer 요청 헤더로 현재 요청을 보낸 페이지의 주소를 알 수 있는데, 해당 주소와 Host(서버의 도메인 이름) 헤더를 비교하여 다른 경우, 예외를 발생시킬 수 있음. 하지만 Referer 요청 헤더는 조작될 수 있다는 점에서 한계가 있음.

  2. CSRF 토큰 방법

    템플릿 엔진 기술(JSP, 타임리프, Pug, Ejs 등) 사용하고 있는 경우라면 CSRF 토큰 방법을 사용해 볼 수 있음. 페이지를 생성하기 이전에 사용자 세션의 임의의 CSRF 토큰을 저장함. 그리고, 특정 API 요청에 대한 제출 폼을 생성할 때 해당 CSRF 토큰값이 설정된 input 태그를 추가함.

<input type="hidden" name="csrf_token" value="csrf_token_12341234"/>

실제로 요청이 전달될 때, 해당 input 태그의 CSRF 토큰과 사용자 세션 내부에 존재하는 CSRF 토큰의 일치 여부를 판단하여, CSRF 공격에 대해 방어할 수 잇음.

이외에도 SameSite 쿠키를 사용하여 크로스 사이트에 대한 쿠키 전송을 제어하거나, 브라우저의 SOP(Same Origin Policy) 정책을 사용하고, CORS 설정으로 교차 출처 접근을 일부분 허용하는 방식으로도 CSRF 공격을 방어할 수 있음.

Last updated

Was this helpful?