Origin 검증 오류

브라우저가 인증 정보를 자동 전송하는 요청에 적절한 출처 검증과 CSRF 방어를 적용하세요.

설명

브라우저가 쿠키 같은 인증 정보를 자동으로 보내는 요청에서 출처 검증과 CSRF 방어가 부족하면, 공격자가 다른 사이트를 통해 사용자의 권한으로 원치 않는 요청을 보낼 수 있습니다. Origin 검증은 사용자 인증을 대신하지 않으며, 브라우저 외의 클라이언트는 이 헤더를 직접 지정할 수 있습니다.

잠재적 영향

  • CSRF 공격: 공격자가 사용자를 대신하여 악의적인 요청을 보내어 무단 액세스를 시도할 수 있습니다.
  • 데이터 유출: 요청으로 정보 공개나 전송 설정이 변경되면 민감한 데이터가 노출될 수 있습니다.
  • 데이터 변조: 공격자가 데이터 변조를 시도하여 시스템 무결성을 손상시킬 수 있습니다.

해결 방법

  • 서버에서 출처의 스킴, 호스트와 포트를 정확한 허용 목록과 비교하세요. Origin 누락과 null 출처를 어떻게 처리할지도 정하세요.
  • 브라우저의 쿠키 인증을 사용하는 상태 변경 요청에는 프레임워크의 CSRF 토큰 검증을 적용하세요.
  • CORS는 신뢰하는 출처에만 응답을 읽을 수 있도록 설정하세요. CORS 설정만으로 CSRF 방어나 인증·권한 검사를 대신하지 마세요.

예시

쿠키 기반 인증을 사용하는 요청 처리의 일부입니다. 인증·권한 검사는 별도로 적용하세요. Flask의 your_secret_key 환경 변수에는 충분히 무작위인 비밀정보를 미리 공급하고, 클라이언트는 유효한 CSRF 토큰을 전송해야 합니다.

Django

변경 전

python
# Unsafe Django code
from django.http import HttpResponse

def my_view(request):
    if request.method == 'POST':
        # CSRF 검증 없이 요청 처리
        return HttpResponse("Request processed")

변경 후

python
# Safe Django code
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_protect

@csrf_protect
def my_view(request):
    if request.method == 'POST':
        # CSRF 토큰을 검증하여 요청 처리
        return HttpResponse("Request processed")

설명:

  • 변경 전: 이 부분에는 CSRF 방어가 나타나지 않습니다. 다른 계층에서도 보호하지 않는 쿠키 인증 요청이라면 CSRF 공격에 노출될 수 있습니다.
  • 변경 후: @csrf_protect로 CSRF 검증을 적용합니다. 변경 전에도 CsrfViewMiddleware가 활성화되어 있으면 보호될 수 있으므로 데코레이터의 부재만으로 판단하지 마세요.

Flask

변경 전

python
# Unsafe Flask code
from flask import Flask, request

app = Flask(__name__)

@app.route('/submit', methods=['POST'])
def submit():
    # CSRF 검증 없이 요청 처리
    return "Request processed"

변경 후

python
# Safe Flask code
import os
from flask import Flask, request
from flask_wtf.csrf import CSRFProtect

app = Flask(__name__)
app.config['SECRET_KEY'] = os.getenv("your_secret_key").encode()
csrf = CSRFProtect(app)

@app.route('/submit', methods=['POST'])
def submit():
    return "Request processed"

설명:

  • 변경 전: 이 부분에는 CSRF 방어가 나타나지 않습니다. 다른 계층에서도 보호하지 않는 쿠키 인증 요청이라면 CSRF 공격에 노출될 수 있습니다.
  • 변경 후: flask_wtf.csrf.CSRFProtect를 사용하여 CSRF 토큰을 검증합니다.

FastAPI

변경 전

python
# Unsafe FastAPI code
from fastapi import FastAPI, Request

app = FastAPI()

@app.post("/submit")
async def submit(request: Request):
    # CSRF 검증 없이 요청 처리
    return {"message": "Request processed"}

변경 후

python
# Safe FastAPI code
from fastapi import FastAPI, Request, HTTPException
from starlette.middleware.trustedhost import TrustedHostMiddleware

app = FastAPI()

# 신뢰할 수 있는 호스트 설정
app.add_middleware(
    TrustedHostMiddleware, allowed_hosts=["example.com", "*.example.com"]
)

@app.post("/submit")
async def submit(request: Request):
    origin = request.headers.get('origin')
    if origin not in ["https://example.com", "https://www.example.com"]:
        raise HTTPException(status_code=403, detail="Invalid origin")
    # 요청 처리
    return {"message": "Request processed"}

설명:

  • 변경 전: 이 부분에는 CSRF 방어가 나타나지 않습니다. 다른 계층에서도 보호하지 않는 쿠키 인증 요청이라면 CSRF 공격에 노출될 수 있습니다.
  • 변경 후: Origin 허용 목록에 없는 값과 누락된 헤더를 거부합니다. TrustedHostMiddleware는 요청 대상의 Host를 검사하는 별도 기능이며 CSRF 방어를 대신하지 않습니다.

참조