drf로 api 서버를 만들고 배포했다. 회원 정보를 어드민 페이지로 관리하기 위해 어드민 개발도 진행했다. 배포 후 어드민 페이지에 접근을 했는데 아래와 같은 에러가 발생했다.
Cross-Site Request Forgery(사이트 간 요청 위조)의 줄임말로, 사용자가 자신의 의지와 무관하게 공격자가 의도한 행동을 해서 특정 웹페이지를 보안에 취약하게 한다거나 수정, 삭제 등의 작업을 하게 만드는 공격 방법이다.
CSRF 오류가 발생하는 이유 중 하나는 HTTP의 Stateless 특성 때문이다. HTTP는 클라이언트와 서버 간의 연결을 유지하지 않는 Stateless한 프로토콜이기 때문에, 요청을 보낼 때마다 새로운 연결이 이루어진다. 이러한 특성으로 인해, 서버는 요청이 유효한지 검증하기 위해 각 요청에 대한 검증 토큰을 발급한다. 하지만 이 토큰이 없는 상황에서 공격자가 인증된 사용자의 브라우저를 통해 요청을 보낸다면, 서버는 해당 요청을 유효하지 않다고 판단하고 차단하게 된다.
Django 프레임워크 사용 시 CSRF 관련 에러를 해결하는 방법은 HTML 폼이나 Ajax 등의 요청에서 CSRF 토큰 포함하여 서버로 요청을 보내는 것이다. 또 다른 방법은 CSRF_TRUSTED_ORIGINS 설정에 신뢰할 수 있는 외부 도메인을 지정하여 해당 도메인에서 오는 요청을 허용할 수 있다. 현 상황에서는 후자의 방법이 더 적합하여 이를 통해 해결해다.
설정파일에 다음의 설정을 추가했다.
CSRF_TRUSTED_ORIGINS = [ https://www.example.com ]
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
CSRF_COOKIE_SECURE = True
CSRF_TRUSTED_ORIGINS 설정은 list 타입으로서 http:// https:// 스키마를 포함한 전체 도메인 주소를 입력해야 한다. 또한 특정 포트로 접근 시 포트 번호까지 명시해야 한다.
CSRF_COOKIE_SECURE 설정은 CSRF 쿠키가 HTTPS를 통해서만 전송되도록 한다. HTTPS를 사용함으로써 네트워크 공격자가 CSRF 쿠키를 탈취하는 것을 방지할 수 있다.
SECURE_PROXY_SSL_HEADER 설정은 Django가 요청이 SSL을 통해 전달된 것인지 여부를 알 수 있도록 도와준다. 특히, 프록시 서버 뒤에 있는 경우 유용하다.
필자 같은 경우는 https를 적용하여 관리자 페이지에 접근하기 때문에 위 설정 모두를 적용하여 문제를 해결할 수 있었다.