CSRF(Cross-Site Request Forgery) 취약점 이해와 방어 방법

안녕하세요! 이번 포스팅에서는 CSRF(Cross-Site Request Forgery) 취약점에 대해 깊이 있게 이해하고, 이를 방어하기 위한 다양한 방법을 소개합니다. CSRF는 웹 애플리케이션의 보안을 위협하는 중요한 취약점입니다.

웹 개발자들은 반드시 이에 대한 대응 방안을 알아야 합니다.

1. CSRF란 무엇인가?

CSRF는 크로스 사이트 요청 위조라고도 불리며, 인터넷 사용자가 자신의 의지와 무관하게 공격자가 의도한 요청을 악의적으로 전송하는 공격 방법입니다. 사용자가 이미 인증된 상태로 웹 애플리케이션에 접속해있을 때, 공격자가 자동으로 특정 요청을 실행시켜 개인 정보 노출, 비정상적인 상태 변경 등을 유발할 수 있습니다.

CSRF ATTACK

2. CSRF 공격의 동작 방식

간단한 CSRF 공격의 작동 방식을 알아보겠습니다

  • 사용자가 해킹 사이트 A에 로그인합니다.
  • 사용자가 해킹 사이트 B에 접속합니다(해킹 사이트 B는 공격자가 운영하는 사이트입니다).
  • 해킹 사이트 B에는 악성 코드가 숨어있는 페이지가 존재합니다. 이 페이지는 사이트 A로 특정 요청을 보내는 코드를 실행합니다.
  • 사용자가 사이트 B를 방문하면, 숨어있는 악성 코드가 자동으로 사이트 A로 요청을 보내게 됩니다.
  • 따라서 사용자는 자신의 의지와 무관하게 악성 요청을 실행하게 됩니다.

다음은 CSRF 공격의 예제 구문 예제를 통해 CSRF 공격의 작동 방식을 이해해보겠습니다.

아래는 간단한 게시물 삭제 기능을 가진 웹 애플리케이션의 코드입니다.

<!DOCTYPE html>
<html>
<body>

<h2>게시물 삭제</h2>
<form action="https://example.com/delete_post" method="post">
  <input type="hidden" name="post_id" value="123">
  <input type="submit" value="게시물 삭제">
</form>

</body>
</html>

이 코드는 게시물 삭제를 위한 폼을 가지고 있습니다. 사용자가 “게시물 삭제” 버튼을 누르면 “https://example.com/delete_post"로 POST 요청이 전송됩니다.

하지만 이 코드에는 CSRF 방어 메커니즘이 없습니다.

3. CSRF의 방어 기법

이제 CSRF 공격으로부터 웹 애플리케이션을 보호하는 방법을 알아보겠습니다.

1. CSRF 토큰

CSRF 토큰을 사용하여 CSRF 공격을 방어 할 수 있는데 CSRF 토큰은 서버가 클라이언트에게 발급하는 임의의 토큰으로, 사용자의 세션과 관련하여 생성됩니다.

이 토큰을 폼과 함께 전송하여, 서버는 해당 토큰의 유효성을 검증합니다.

예제 구문:

<!DOCTYPE html>
<html>
<body>

<h2>게시물 삭제</h2>
<form action="https://example.com/delete_post" method="post">
  <input type="hidden" name="csrf_token" value="무작위_토큰_값">
  <input type="hidden" name="post_id" value="123">
  <input type="submit" value="게시물 삭제">
</form>

</body>
</html>

CSRF 토큰은 서버에서 생성되어 클라이언트로 전송되어야 합니다. 서버는 요청을 받을 때 해당 토큰의 유효성을 확인하고, 유효하지 않은 경우 요청을 거부합니다. 이러한 CSRF 토큰을 사용하여 보안을 강화할 수 있습니다.

2. SameSite 쿠키 속성 설정

SameSite 쿠키 속성은 웹 사이트에서 쿠키를 사용할 때 Cross-Site 요청을 방지하는데 도움이 됩니다. 이 속성을 설정하면, 해당 도메인을 출처로 하는 요청에서만 쿠키가 전송되도록 제한할 수 있습니다.

예제 구문:

// 서버 응답에 쿠키 설정 예제
Set-Cookie: session_id=세션_ID; SameSite=Strict; Secure;

SameSite 속성을 “Strict”로 설정하면 동일 출처 요청에서만 쿠키가 전송되며, “Lax”로 설정하면 일부 상황에서 Cross-Site 요청에서도 쿠키가 전송됩니다.

“None”으로 설정하면 모든 요청에서 쿠키가 전송되지만, Secure 속성과 함께 사용해야 하며 HTTPS에서만 동작합니다. 이를 통해 웹 애플리케이션의 쿠키 보안을 강화할 수 있습니다.

3. Referrer Policy 설정

Referrer Policy를 적절히 설정하여 CSRF 공격을 방어할 수 있습니다.

Referrer는 웹 페이지로 이동한 원래 출처(Referer)를 나타내는 헤더입니다. Referrer Policy를 설정하여 Cross-Site Referrer 정보를 제한하거나 제거할 수 있습니다.

예제 구문:

<!-- HTML 문서의 head 태그 내에 Referrer Policy 설정 -->
<head>
  <meta name="referrer" content="same-origin">
</head>

위의 예제에서 content 값을 “same-origin”으로 설정하면, 리퍼러는 동일 출처에서만 전송됩니다. 이를 통해 웹 애플리케이션의 보안을 강화할 수 있습니다.

4. CSRF 방어를 위한 추가적인 보안 기법

  1. 적절한 HTTP 메서드 사용 웹 애플리케이션에서는 안전한 HTTP 메서드(GET, HEAD, OPTIONS)를 사용하거나, CSRF에 취약하지 않은 메서드(POST, PUT, DELETE)를 사용하여 요청을 처리하는 것이 중요합니다.
  2. CORS(Cross-Origin Resource Sharing) 설정 CORS를 사용하여 다른 출처로부터의 요청을 제한하는 것도 CSRF 방어에 도움이 됩니다. CORS 설정을 통해 특정 도메인에서만 요청이 허용되도록 할 수 있습니다.

4. CSRF 방어 실습(세부 과정)

1. CSRF 토큰을 사용한 방어

CSRF 토큰은 서버가 클라이언트에게 발급하는 임의의 토큰으로, 사용자의 세션과 관련하여 생성됩니다. 이 토큰을 폼과 함께 전송하여, 서버는 해당 토큰의 유효성을 검증합니다.

실습 코드

  1. 서버 측 코드 (Python – Flask)
from flask import Flask, render_template, request, make_response
import secrets

app = Flask(__name__)

@app.route('/form', methods=['GET', 'POST'])
def csrf_form():
    if request.method == 'POST':
        csrf_token = request.form['csrf_token']
        # CSRF 토큰 검증
        if csrf_token == session['csrf_token']:
            # 유효한 요청 처리
            return 'CSRF 방어 성공! 정상적으로 요청을 처리합니다.'
        else:
            # 유효하지 않은 요청 처리
            return 'CSRF 방어 실패! 유효하지 않은 요청입니다.'
    else:
        # CSRF 토큰 생성 및 세션에 저장
        session['csrf_token'] = secrets.token_hex(32)
        return render_template('csrf_form.html', csrf_token=session['csrf_token'])

if __name__ == '__main__':
    app.run()

2. 템플릿 파일 (csrf_form.html)

<!DOCTYPE html>
<html>
<head>
    <title>CSRF 방어 실습 폼</title>
</head>
<body>
    <h2>CSRF 방어 실습 폼</h2>
    <form action="/form" method="post">
        <input type="hidden" name="csrf_token" value="{{ csrf_token }}">
        <input type="submit" value="요청 전송">
    </form>
</body>
</html>

2. SameSite 쿠키 속성 설정

SameSite 쿠키 속성은 웹 사이트에서 쿠키를 사용할 때 Cross-Site 요청을 방지하는데 도움이 됩니다. 이 속성을 설정하면, 해당 도메인을 출처로 하는 요청에서만 쿠키가 전송되도록 제한할 수 있습니다.

실습 코드

  1. 서버 측 코드 (Python – Flask)
from flask import Flask, render_template, make_response

app = Flask(__name__)

@app.route('/')
def set_cookie():
    # SameSite 쿠키 설정
    response = make_response("SameSite 쿠키 설정 예제")
    response.set_cookie("session_id", "세션_ID", samesite='Strict', secure=True)
    return response

if __name__ == '__main__':
    app.run()

3. Referrer Policy 설정

Referrer Policy를 적절히 설정하여 CSRF 공격을 방어할 수 있습니다. Referrer는 웹 페이지로 이동한 원래 출처(Referer)를 나타내는 헤더입니다. Referrer Policy를 설정하여 Cross-Site Referrer 정보를 제한하거나 제거할 수 있습니다.

실습 코드

  1. 서버 측 코드 (Python – Flask)
from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def index():
    return render_template('index.html')

if __name__ == '__main__':
    app.run()
<!DOCTYPE html>
<html>
<head>
    <title>Referrer Policy 설정 실습</title>
    <!-- Referrer Policy 설정 -->
    <meta name="referrer" content="same-origin">
</head>
<body>
    <h2>Referrer Policy 설정 실습</h2>
    <a href="https://example.com" target="_blank">외부 링크 (same-origin)</a>
</body>
</html>

위의 코드는 Flask 웹 애플리케이션을 구성한 예시입니다. CSRF 토큰을 사용한 방어, SameSite 쿠키 속성 설정, Referrer Policy 설정에 대한 예시를 보여주고 있습니다.

이렇게 설정하면 웹 애플리케이션은 CSRF 공격으로부터 더욱 안전하게 보호될 수 있습니다.

결론

CSRF(Cross-Site Request Forgery) 취약점은 웹 애플리케이션 보안에 중요한 영향을 미치는 취약점 중 하나입니다. 악의적인 요청을 방지하기 위해 CSRF 토큰과 SameSite 쿠키 속성, Referrer Policy 등의 방어 기법을 적용하는 것이 필수적입니다. 또한 적절한 HTTP 메서드 사용과 CORS 설정을 고려하여 웹 애플리케이션의 보안성을 높이는 것이 중요합니다.

자주 묻는 질문 (FAQs)

Q1: CSRF와 XSS는 같은 취약점인가요?

A: 아니요, CSRF와 XSS는 서로 다른 취약점입니다. CSRF는 인증된 사용자의 요청을 악용하는 것이며, XSS는 사용자에게 악성 스크립트를 주입하는 것입니다.

Q2: CSRF 토큰은 어떻게 생성되나요?

A: CSRF 토큰은 보안적으로 안전한 난수를 생성하여 사용자 세션과 관련하여 발급합니다.

Q3: SameSite 쿠키 속성은 어떤 브라우저에서 지원되나요?

A: SameSite 쿠키 속성은 Chrome 51 버전부터 지원되며, 대부분의 최신 브라우저에서 지원됩니다.

Q4: 웹 방화벽을 사용하는 것이 CSRF 방어에 도움이 되나요?

A: 네, 웹 방화벽은 추가적인 보안 레이어를 제공하여 CSRF 공격을 탐지하고 차단하는 데에 도움이 됩니다.

Q5: CSRF 방어를 위해 CORS 설정은 꼭 필요한가요?

A: CSRF 방어를 위해 CORS 설정은 필수적이지 않지만, 다른 보안 취약점과 함께 사용하면 웹 애플리케이션 보안을 강화할 수 있습니다.

긴 포스팅 글을 정독해 주셔서 감사합니다.

<Reference>
1. Cross-Site Request Forgery (CSRF): Impact, Examples, and Prevention (brightsec.com)
2. CSRF Attacks: Anatomy, Prevention, and XSRF Tokens | Acunetix

댓글 남기기