[Spring Security] CSRF공격과 대응방법

nana·2025년 3월 4일

SpringSecurity

목록 보기
1/1
post-thumbnail

💡사이트 간 요청 위조(Cross-site Request Forgery, CSRF)
: 사용자가 자신의 의지와 상관없이 공격자가 의도한 행위(ex. 보안에 취약하게 만들기 / 수정 또는 삭제 등의 작업하게 만들기)를 특정 웹사이트에 요청하도록 하는 것을 의미

XSS 공격과 차이

XSS공격 (사이트 간 스크립팅)공격 : 사용자가 웹사이트를 신용하여 악성스크립트가 실행됨.
CSRF공격 : 특정 웹사이트가 사용자의 브라우저를 신용하여 발생.
✅ XXS는 악성 코드가 클라이언트에서 발생, CSRF는 악성코드가 서버에서 발생.

CSRF 공격 방법

  • 공격자는 이메일이나 게시판에 CSRF 스크립트가 포함된 게시물을 전송한다.
  • 관리자는 공격자가 등록한 CSRF 스크립트가 포함된 게시물을 확인한다.
  • 관리자가 CSRF스크립트가 포함된 게시물을 열람하면, 관리자의 권한으로 공격자가 원하는 CSRF스크립트 요청이 발생한다.
  • 공격자가 원하는 CSRF스크립트가 실행되어, 관리자 및 사용자의 피해가 발생한다.

ex) 공격자가 만든 사이트 내부에 다음과 같은 태그가 존재할 수 있다.
<img src ="https://velog.io/member/changePassword?newpassword=aaaa1111"/>

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

CSRF 공격은 어떻게 방어할까?

1. HTTP 헤더 중 하나인 Referer요청 헤더 사용

  • HTTP 헤더에 있는 Referer로 해당 요청이 요청된 페이지의 정보를 확인하는 방법.
  • 간단해서 소규모 웹사이트에 주로 이용됨.
  • 해당 정보는 Paros나 Zap, fiddler같은 프로그램으로 조작 가능.

2. GET/POST 요청 구분

  • img 태그 등의 경우 GET요청으로, form 태그로 받을 경우 POST를 이용하여 요청을 구분해줌.
    ex)
    중요한 요청의 경우 POST방식으로만 받을 수 있도록 변경하면 된다.
<form method="POST" action="https://victim.com/transfer">
    <input type="hidden" name="amount" value="10000">
    <input type="hidden" name="to" value="hacker">
    <input type="submit" value="전송">
</form>

이렇게 하면 GET요청을 통한 자동 실행 방지가 된다.
<img> 태그나 <script> 태그로는 POST 요청을 보낼 수 없음 → 공격이 어려워짐.

ex2)

@RestController
@RequestMapping("/api")
public class TransferController {

   @PostMapping("/transfer")
   public ResponseEntity<String> transferMoney(
           @RequestParam int amount,
           @RequestParam String to,
           HttpServletRequest request) {

       // GET 요청 차단 (이 코드는 사실 필요 없음, @PostMapping 자체가 POST만 허용)
       if (!request.getMethod().equalsIgnoreCase("POST")) {
           return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
                   .body("GET 요청은 허용되지 않습니다.");
       }

       // 실제 송금 처리 로직 (예제이므로 로직은 생략)
       return ResponseEntity.ok("송금 완료");
   }
}

3. CSRF 토큰 방법 사용.

CSRF토큰이란?
서버측 애플리케이션에서 생성되고 클라이언트와 공유되는 인증 값.
클라이언트는 서버의 통신에 올바른 CSRF토큰을 포함해야한다.
그렇지 않으면 서버는 요청된 작업 수행을 거부한다.
CSRF 토큰을 클라이언트와 공유하는 일반적인 방법은 HTML 형식의 숨겨진 매개변수로 포함하는 것.

  • 보통의 CSRF Token은 hidden상태로 보안되어있다.

4. 그 외

브라우저의 SameOrigin 정책을 이용.
SameOrigin이 아닌 경우 JavaScript로 쿠키값을 확인하거나 수정하지 못한다는 점을 이용한 검증방법.
동일한 도메인 주소에서 동작하도록 해당 사이트에 게시글등을 통해 악성 스크립트를 심는 경우 이 방어는 무효하다.
도메인이 다른 사이트를 이용해 공격하는 경우에만 방어 코드가 유효하다.

SameOrigin
Same-Origin(동일 출처) 정책(SOP, Same-OriginP Policy)은 웹 보안 모델 중 하나로, 다른 출처(origin)에서 온 리소스에 대한 접근을 제한하는 정책이다.
웹 브라우저는 기본적으로 동일출처에서만 리소스를 공유할 수 있도록 제한하고, 다른 출처의 리소스를 불러오려면 CORS(Cross-Origin Resource Sharing)같은 특별한 방법이 필요하다.

추가.

스프링 시큐리티 관련 자료들에서 CSRF설정을 종종 비활성화시키곤 한다.

@Override
    public void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();
    }

스프링 시큐리티 프레임워크는 기본적으로 CSRF공격에 대한 방어를 수행한다.
CSRF공격에 대처할 설정을 disable시키는 것이 과연 좋은 방법일까?
CSRF공격은 쿠키가 없으면 불가능하다. 브라우저에 저장되는 쿠키가 CSRF공격의 매개체이기 때문이다.

REST API방식은 쿠키나 세션에 의존하지 않는 경향이 크므로 CSRF공격에 대한 방어 설정을 비활성화 시키는 경우가 많으며, 쿠키 대신에 로컬스토리지(localStorage), 세션 대신 JWT(Json Web Token)를 사용하면 CSRF공격에 대한 방어가 필요 없다.


CSRF 공격과 방어 기법
CSRF TOKEN에 관하여
CSRF공격과 방어

profile
BackEnd Developer, 기록의 힘을 믿습니다.

0개의 댓글