CSRF 공격에 대해

songh·2024년 12월 3일
0

CS지식

목록 보기
32/35
post-thumbnail

1. CSRF 공격


Cross Site Request Forgery : 사이트간 요청위조, 웹사이트 취약점 공격 중 하나에 속함

  • 사용자가 자신의 의지와는 무관하게, 공격자가 의도한 행위(삭제, 수정 등등)을 특정 웹사이트에 요청하는 공격을 말한다.
  • 공격자가 만든 악성 페이지를 통해, 사용자가 자신도 모르게 서버를 공격하게 된다.
  • 쿠키에 SessionId가 담겨있어서, 누군가 악성 스크립트로 요청을 강제하면, 사용자의 요청과 무관하게 요청이 이뤄질 수 있음을 이용한 공격방법이다.

**
**
XSS와 CSRF의 차이

  • XSS : 사용자가 특정 웹사이트를 신용한점을 노린 공격(악성코드가 클라이언트쪽에서 발생한다)
  • CSRF: 특정 웹사이트가 사용자의 브라우저를 신용한 점을 노린 공격(악성코드가 서버에서 발생한다)

2. CSRF 공격을 하기위한 조건


전제조건을 만족해야 한다.

(1) 사용자(희생자, 자기도 모르게 공격되는 사람)은 보안이 취약한 서버에 이미 로그인 되어있어야 한다.

(2) 쿠키 기반의 서버 세션정보를 획득할 수 있어야한다.

(3) 공격자는 서버를 공격하기 위한 요청방법을 미리 파악하고 있어야 한다.

▪️ 예상치못한 파라미터가 있으면 불가능하다.


3. CSRF 공격은 어떻게?


(1) 먼저 공격자는 “조건 3번”을 통해서 서버를 공격하기 위한 요청방법을 미리 파악하고 있는 상태다.

(2) 아무것도 모르는 사용자(희생자)는 보안이 취약한 서버에 로그인한다.
로그인 이후, 세션정보를 활용할 수 있는 sessionID가 사용자 브라우저 쿠키에 저장된다.

(3) 공격자는, 서버에 인증된 브라우저 사용자가 악성 스크립트 페이지를 누르도록 유도한다.

(4) 사용자가 악성 스크립트가 담긴 페이지 접근시, 쿠키에 저장된 SessionID는 브라우저에 의해 자동적으로 함께 서버에 요청된다.

(5) 서버는 쿠키에 담긴 SessionId를 통해 이미 인증받은 사용자에게 온 것으로 인식하고 요청에 대한 처리를 하게 된다.
즉, 공격자가 의도한 행동을 하게 된다.


4. CSRF disable


가끔 프로젝트 코드를 보면 csrf를 disable()한 것을 볼 수 있다.


  • Gradle에 spring-boot-starter security를 추가하고, SecurityConfig 클래스를 만들어주면, CSRF 공격으로부터 방지할 수 있다.
implementation 'org.springframework.boot:spring-boot-starter-security'

@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter { }

따라서 악성 스크립트 페이지를 요청하려고 할 때 403 forbidden 으로 반환해서 막아준다.

근데 왜 disable할까?

  • CSRF 공격을 위한 전제조건은, 쿠키 기반의 세션정보를 얻어와야 인증을 받고 공격이 가능하다.
  • REST API를 이용하는 서버라면, 서버는 ‘Stateless’하므로 서버가 클라이언트의 인증정보를 보관하고 있지 않는다. 대신 JWT로 토큰을 이용해 인증하기 때문에 서버에서 인증정보를 저장하지 않아서, 굳이 불필요하게 CSRF 공격을 막을 필요가 없다. 그래서 disable( ) 하는 걸로 보인다.
@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();
    }
}

5. CSRF 공격을 받는 방법


(1) Check Referrer

서버에서 사용자의 요청헤더에서 Referrer 정보를 확인하는 방법이다. 보통 호스트와 Referrer 값이 일치하므로 둘을 비교한다. 대부분 Referrer 값에 대한 검증만으로 방어가 가능하다고 한다.

String referer = request.getHeader("Referer");
        String host = request.getHeader("host");
        if (referer == null || !referer.contains(host)) {
            response.sendRedirect("/");
            return false;
        }
        return true;

(2) CSRF 토큰

임의의 CSRF 토큰을 만들고 세션에 저장한다. 이후 요청하는 페이지에 hidden타입의 input 태그로 토큰값을 함께 전달한다. 이후 서버에서 세션에 저장된 CSRF 토큰값과 요청 파라미터에 담긴 토큰값을 비교한다.


사용자가 특정 서버에 로그인하려면 일반적으로 아래의 작업이 수행된다.

(1) 서버는 로그인시 인증된 사용자의 정보를 세션에 저장하고, 이를 찾을 수 있는 sessionId를 만든다.

(2) 서버는 저장된 세션정보를 클라이언트(브라우저)가 사용할 수 있도록 sessionID를 set-Cookie 헤더에 담아서 전달한다.

(3) 클라이언트는 전달된 sessionID를 쿠키에 저장한다.

(4) 클라이언트는 같은 서버에 요청할 때 쿠키에 저장된 sessionID를 자동으로 쿠키에 담아 전달한다.
(5) 서버는 쿠키에 담긴 sessionID를 통해 인증된 사용자인지 여부를 확인해서 응답을 보낸다.


Reference

Spring security - csrf란?
CSRF(Cross-Site Request Forgery) Attack and Defence

0개의 댓글

관련 채용 정보