0308 TIL

looggi·2023년 3월 8일
0

TILs

목록 보기
29/114
post-thumbnail

django

CSRF Error

  1. Template Engine을 사용할 때, 발생하는 CSRF Error가 무엇이고 어떻게 해결합니까?
    인증된 사용자에 대해서 서버가 사용자를 신뢰하는 것을 이용한 공격으로 사용자가 의도하지 않은 위조된 요청을 서버에 보내게 되어 서버가 공격을 받게 됩니다.
    이 에러를 해결하는 방법으로는 시큐리티 토큰을 사용하는 방법과 리퍼러를 사용하는 방법이 있는데 리퍼러를 체크하는 방법은 요청의 리퍼러와 도메인이 일치하는지를 확인하는 것으로 프로젝트의 settings.py에서 CSRF_TRUSTED_ORIGIN에 허용 도메인을 추가해서 안전하지 않은 요청을 보낼 필요가 있는 도메인의 요청을 에러없이 처리할 수 있다.
    시큐리티 토큰을 사용하는 방법은 사용자의 요청에 난수값을 포함시켜 세션에 저장된 토큰 값과 요청 파라미터에 전달되는 토큰값이 일치하는지 확인하는 것으로 장고 템플릿에서 폼태그 POST 요청시에 {% csrf_token %}을 써줌으로써 사용할 수 있다.

⚡ CSRF

Cross-Site Request Forgery
특정 웹사이트(서버)가 사용자의 웹 브라우저를 신용하는 상태를 노린 것
로그인한 사용자가 CSRF 코드가 삽입된 페이지를 열면 서버는 위조된 공격 명령이 믿을 수 있는 사용자로부터 발송된 것으로 판단하기때문에 공격에 노출된다

사용자가 자신의 의지와 무관하게 공격자가 의도한 행동을 해서 특정 웹페이지를 보안에 취약하게 한다거나 수정, 삭제 등의 작업을 하게 만드는 공격 방법

웹페이지의 취약점을 이용해서 공개된 게시판이나 메일을 이용해서 사용자가 해당 링크를 열게 만드는 방식(피싱)으로 공격할 수 있다

*authenticated된 request에 대해서만(로그인한 유저의 요청에 대해서만) CSRF토큰을 필요로 하며, anonymous request에 대해서는 CSRF토큰을 검증하는 과정을 거치지 않는다 따라서 로그인한 유저에 대해서 403 CSRF 에러가 발생한다
https://mrclap.github.io/posts/django/2019-05-28-django-auth-with-DRF/

⚡ CSRF error 예방하기

① Referer 체크를 하는 방법

  • Referer: HTTP 헤더에 있는 정보로 해당 요청이 요청된 페이지의 정보를 가지고 있다

request의 referrer를 검증하여 도메인이 일치하는지 확인한다

② security token 사용하는 방법(CSRF token)
사용자의 요청에 난수값을 포함시켜 세션에 저장된 토큰 값(임의의 난수)과 요청 파라미터에 전달되는 토큰 값이 일치하는지 검증

장고템플릿에서 폼태그를 전송할 때(POST 外) {% csrf_token %} 를 반드시 써줘야한다

  • 서버가 클라이언트 세션에 토큰을 저장하고 이후 해당 템플릿태그가 포함된 모든 요청에 대해서 서버의 토큰과 클라이언트의 토큰이 일치하는지 확인

①, ②는 xss 공경에 대한 취약점이 있다면 csrf 공격에도 취약해짐

  • xss: Cross site Scripting
    권한 없는 사용자가 웹서비스에 스크립트를 삽입하는 공격 기법
    사용자의 입력에 대한 검증이 없기 때문에 발생

③ Double Submit Cookie
Security Token 검증의 한 종류로 세션을 사용할 수 없는 환경에서 사용할 수 있는 방법으로 웹브라우저의 Same Origin 정책으로 인해 자바스크립트에서 타 도메인의 쿠키 값을 확인/수정하지 못한다는 것을 이용한 방어 기법
스크립트 단에서 요청 시 난수 값을 생성하여 쿠키에 저장하고 동일한 난수 값을 요청 파라미터(혹은 헤더)에도 저장하여 서버로 전송합니다. 서버단에서는 쿠키의 토큰 값와 파라미터의 토큰 값이 일치하는지 검사

  • 피싱 사이트에서는 도메인이 달라 해당사이트 도메인에 쿠키에 값을 저장하지 못하는 것을 이용한 (Same Origin 정책) 방어 기법
    • 웹브라우저의 Same Origin 정책: 자바스크립트에서 타 도메인의 쿠키 값을 확인/수정하지 못한다

④ GET/POST를 구분해서 요청하는 방법 △
unsafe method를 사용했을 때 리퍼러/헤더 오리진 체크를 할 수 있어서 그런듯
애초에 로그인한 사용자가 unsafe method로 request를 보낼 때 CSRF 토큰이 없으면 403오류가 남
form에 반드시 붙여 보내는 게 form작성/수정하는 게 모두 unsafe method니까

⚡ 장고에서 CSRF 검증 실패 error 해결하기

① settings.py, views.py 수정
settings.py MIDDLEWARE - CSRF 부분 주석처리
views.py from django.views.decorators.csrf import csrf_exempt 데코레이더로 해당 Class 데코레이트

csrf_exempt <-> csrf_protect
requires_csrf_token : 템플릿태그가 확실하게 작동하는 것을 확인할 수 있는 데코레이터
② settings.py만 수정
MIDDLEWARE - security, csrf, auth 부분 주석처리

①, ②는 안전하지 않은 해결방법

③ 허용 도메인 추가
settings.py CSRF_TRUSTED_ORIGINS
안전하지 않은 요청(POST 外)에 대한 믿을 수 있는 오리진 리스트를 작성
기본값은 빈 리스트

장고의 CSRF 프로텍션 방침에 의해서

  • 오리진 헤더를 포함하는 요청은 호스트의 헤더에 있는 오리진과 일치하는 헤더가 있어야 한다 또는 CSRF_TRUSTED_ORIGINS에 있어야한다
    • 오리진: 도메인, 프로토콜, 포트로 구성
  • 오리진 헤더를 포함하지 않는 보안된(SECURE->HTTPS) 안전하지 않은 요청은 호스트의 헤더에 있는 오리진과 일치하는 Referer 헤더가 있어야한다

🧟 CSRF 검증 실패 에러가 나는 다른 이유와 해결방법

CSRF 토큰은 로그인할 때마다 바뀌는데 로그인 이전에 생성된 폼이 있는 페이지는 유효하지 않은 토큰을 가지고 있어서 리로드가 필요하다
로그인 후 뒤로가기 버튼을 누르거나 다른 브라우저 탭에서 로그인하는 경우 이런 에러가 발생할 수 있다

⚡ 장고의 CSRF protection

  1. CsrfViewMiddleware가 응답시 django.middleware.csrf.get_token()이 호출될 때마다 CSRF 쿠키를 같이 보낸다. 안전을 위해 유저가 로그인할 때마다 값은 변경된다

    • CSRF 쿠키: 타 사이트가 접근할 수 없는 랜덤 시크릿 밸류
  2. POST 폼에는 csrfmiddlewaretoken라는 숨겨진 폼필드가 있는데 템플릿 태그 {% csrf_token %} 사용시 get_token()이 호출되면서 mask가 생성되어 response와 섞이면서 이 필드의 값이 보호된다.

  3. 모든 요청(HTTP GET, HEAD, OPTIONS or TRACE-safe method-이 아닌)에 대해서 CSRF 쿠키는 반드시 존재해야하고 csrfmiddlewaretoken 필드 또한 반드시 존재하고 멀쩡해야한다. 아니라면 403 에러를 발생시킨다.

    • CsrfViewMiddleware가 csrfmiddlewaretoken필드의 시크릿 부분과 쿠키값의 시크릿 부분을 비교하여 검증한다(토큰 전체를 비교하지 않는다)
  4. CsrfViewMiddleware는 current host와 CSRF_TRUSTED_ORIGINS 목록에 대해서 Origin 헤더를 검증해서 cross-subdomain attacks을 예방한다

  5. Origin 헤더가 없는 HTTPS requests에 대해서 CsrfViewMiddleware는 리퍼러 체크를 진행한다.

    • 서브도메인이 도메인의 쿠키를 설정하거나 수정할 수 있더라도 요청이 정확히 같은 도메인에서 온 게 아니기때문에 서브도메인에서는 리퀘스트를 강제로 보낼 수 없다
    • HTTP 리퀘스트에 대해서는 리퍼러 체킹을 하지 않는다
    • CSRF_COOKIE_DOMAIN이 설정되어있다면 리퍼러 체크에 사용하며 설정되어있지 않다면 리퍼러는 HTTP Host 헤더(도메인+포트)와 같아야한다
    • CSRF_COOKIE_DOMAIN = '.example.com'라고 설정해두면 해당 도메인 및 서브도메인의 POST요청을 허용한다
    • CSRF_TRUSTED_ORIGINS 설정을 통해 accepted referer를 추가할 수 있다

➡️ 이를 통해 신뢰할 수 있는 도메인만이 POST요청을 보낼 수 있다

safe method를 통한 요청은 무시한다

  • safe method란 클라이언트가 오리진 서버의 타겟 리소스에 대해 safe method 통해 요청할 때 서버 상태가 변경될 것이라고 예상하지도, 요청하지도 않는 것(read-only)
  • unsafe method: POST, PUT, and DELETE

➡️ CSRF protection의 한계

man-in-the-middle attack을 방지할 수 없다.

https://itstory.tk/entry/CSRF-%EA%B3%B5%EA%B2%A9%EC%9D%B4%EB%9E%80-%EA%B7%B8%EB%A6%AC%EA%B3%A0-CSRF-%EB%B0%A9%EC%96%B4-%EB%B0%A9%EB%B2%95
https://dpcalfola.tistory.com/entry/Django-pojc-E5-CSRF-token%EC%97%90-%EB%8C%80%ED%95%98%EC%97%AC-%ED%86%A0%ED%81%B0-%EA%B2%80%EC%A6%9D-%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EB%A7%88%EA%B0%90-%EC%B6%94%EA%B0%80%EA%B8%80-2%EB%B2%88
https://namu.wiki/w/CSRF
https://grooveshark.tistory.com/73
https://docs.djangoproject.com/en/4.1/ref/csrf/#django.views.decorators.csrf.ensure_csrf_cookie

Template Engine 🔗

템플릿 양식과 특정 데이터 모델에 따른 입력 자료를 합성하여 결과 문서를 출력하는 소프트웨어(또는 소프트웨어 컴포넌트)

  • 웹 템플릿 엔진: 웹 문서가 출력되는 템플릿 엔진
    웹 템플릿들(web templates)과 웹 컨텐츠 정보(content information)를 처리하기 위해 설계된 소프트웨어
    view code(html)와 data logic code(db connection)를 분리해준다
  • 템플릿 시스템

https://gmlwjd9405.github.io/2018/12/21/template-engine.html

DRF

  1. DRF를 사용해 API를 개발할 경우 어떤 장점이 있습니까?
    REST API 서버를 쉽게 구축할 수 있습니다.

Django Rest Framework

DRF의 API View는 FBV와 CBV가 있고 CBV가 class의 장점을 이용해서 코드를 간소화할 수 있음

스마트폰 출시 이후 어플리케이션의 등장으로 더 이상 웹으로만은 서비스를 제공할 수 없었다. 즉, HTML로 렌더링하는 웹 서버가 아닌, JSON 혹은 XML과 같은 형식을 통해 데이터를 다루는 별도의 API 서버가 필요해진 것이다. (생각해보면 웹이나 앱이나 제공하는 기능과 주고받는 데이터가 동일한데 기존의 웹 서버만을 사용하여 매번 HTML을 읽고 --> 해당 태그에 들어있는 정보를 찾아내어 --> 스마트폰 화면에 띄우는 절차를 진행하는 것은 상당히 비효율적인 일이다.)
https://velog.io/@ifyouseeksoomi/DRF-Django-REST-Framework-%EA%B0%84%EB%8B%A8%ED%95%9C-%EC%98%88%EC%8A%B5-Serializer

API는 무엇을 의미하나요?

API는 Application Programming Interface (애플리케이션 프로그램 인터페이스)의 줄임말입니다. API의 맥락에서 애플리케이션이라는 단어는 고유한 기능을 가진 모든 소프트웨어를 나타냅니다. 인터페이스는 두 애플리케이션 간의 서비스 계약이라고 할 수 있습니다. 이 계약은 요청과 응답을 사용하여 두 애플리케이션이 서로 통신하는 방법을 정의합니다.
API 문서에는 개발자가 이러한 요청과 응답을 구성하는 방법에 대한 정보가 들어 있습니다.
https://aws.amazon.com/ko/what-is/api/

https://blog.naver.com/sw_maestro/222930071929

  1. Django 와 DRF를 통한 개발의 차이점은 어떤 것이 있습니까?
    DRF에는 serialize기능이 있습니다. 시리얼라이저는 DB 데이터(ORM/nonORM 모두)를 JSON형식으로 변환해주는데 JSON형식으로 변환된 데이터는 특정 프로그래밍 언어에 종속되지 않아 다른 언어로 구현된 프론트엔드와 데이터 전송이 쉽고 비교적 가벼워 전송 속도가 빠르다는 장점이 있습니다.

JSON

장점

함축적으로 최소한의 정보만을 가지고 있어 XML 에 비해 용량이 줄어들어 속도가 빠르다

  • XML은 헤더와 태그 등의 여러 요소로 가독성이 떨어지고, 쓸데없이 용량을 잡아먹는다
  • XML에는 스키마(Schema)가 있어서 데이터의 무결성을 검증할 수 있다.

프로그래밍 언어와 플랫폼에 독립적이므로, 서로 다른 시스템간에 객체를 교환하기에 좋다.
대부분의 최신 웹 브라우저는 JSON 전용 parser 기능을 내장하고 있으므로 이런 기능을 사용하는 것이 더 안전할 뿐만 아니라 빠른 방법이다.

  • 웹 브라우저가 주가 되는 환경, 특히 사용자에게 보여주는 HTML 과 이를 실시간으로 가공하는 JavaScript가 연동하는 환경 위주로 퍼지고 있으며, 그렇지 않은 곳에서는 여전히 XML을 사용하는데 문제가없다

DOM을 사용하는 것보다

  • DOM: 웹 페이지(HTML이나 XML 문서)의 콘텐츠 및 구조, 그리고 스타일 요소를 구조화 시켜 표현하여 프로그래밍 언어가 해당 문서에 접근하여 읽고 조작할 수 있도록 API를 제공하는 일종의 인터페이스

단점

대용량급의 데이터 송수신에는 부적합한 모습도 있습니다.

무결성을 검증하지 않는다

  • 적용되는 곳이 늘어남에 따라 XML과 같이 valid한 검증이 필요해졌으며, Namespace 문제가 발생하는 경우가 늘고 있다.
  • 이를 극복하기 위해 JSON-Schema, JSON-LD(JSON Linking Data) 같은 것이 등장하고 있다.
    • 사용처마다 요구되는 구조와 형태를 잘 갖췄는지 검증할 수 있음

https://ko.wikipedia.org/wiki/JSON
https://namu.wiki/w/JSON
https://velog.io/@seongguk/JSON-vs-XML

django ORM method

Q( )

  1. DRF Q기능을 통해서 쿼리하는 것은 어떤 장점이 있습니까?
    큐 객체는 복잡한 조건의 쿼리문을 만들 때 사용합니다. 데이터 작업을 할 때 자주 사용하는 필터함수의 경우 기본적으로 ,를 통해 and연산을 제공하지만 or이나 like와 같은 연산은 제공하지 않기때문에 q를 이용해서 sql과 같은 쿼리를 작성할 수 있게 됩니다.

데이터를 필터링해서 검색할 때 검색조건이 복잡할 때 사용하기 좋고 filter 안에서 or연산이 가능합니다.

  • 그냥 OR 사용하려면 필터 밖에서는 쓸 수 있음
    ex. 필터한거 | 필터한거
  • 데이터를 필터링할 때 AND,OR,NOT등의 파이썬 문법을 그대로 사용할 수 있습니다
# filter 외부에서 OR 연산자 사용
Product.objects.filter(id__gt=6) | Product.objects.filter(name__contains = "ooo")

# filter 내부에서 OR 연산자 사용
Products.object.filter(Q(name='velog')|Q(created_at='2022-08-29'))

# 객체 가져오기
Q(Product) # == Product.objects.all() 

lookup filter 👀

filter(), exclude() 메소드에서 사용 가능한 내장 모듈

  • __contains: 문자열 포함여부 체크. 대소문자 구분
  • __gt : 특정 값 보다 큰 데이터만 조회

https://devvvyang.tistory.com/37

permission_classes

  1. DRF permission_classes를 사용하는 이유는 무엇입니까?
    어플리케이션 사용자의 이용범위를 설정하기 위해서 사용합니다.

🤠 permission_classes 종류

  • AllowAny (디폴트 전역 설정) : 인증 여부에 상관없이 뷰 호출을 허용
  • IsAuthenticated : 인증된 요청에 한해서 뷰 호출 허용 (로그인이 되어있어야만 접근 허용)
  • IsAdminUser : Staff 인증 요청에 한해서 뷰 호출 허용
    IsAuthenticatedOrReadOnly : 비인증 유저에게는 읽기 권한만 허용
  • DjangoModelPermissons : 인증된 요청에 한하여 뷰 호출 허용 + 추가로 장고 모델단위 Permissions 체크
  • DjangoModelPermissionsOrAnonReadOnly : DjangoModelPermissions + 비인증 유저는 읽기만 허용
  • DjangoObjectPermissons : 비인증 요청은 거부, 인증된 요청은 Object에 대한 권한 체크 수행
# example on CBV
from rest_framework.permissions import IsAuthenticated

class ExampleView(APIView):
   permissions_classes = [IsAuthenticated]
   
   def get(self, request, format=None):
       content = {'status' : 'request was permitted'}
       return Response(content)

🤠 커스텀 Permission

  • has_permission(request, view)
  • has_object_permission(request, view, obj)
    ex. 작성자에 한해 게시글(obj) 수정/삭제 허용

두가지 메서드를 사용해서 원하는 permission 구현할 수 있음
*장고의 모든 permission class는 이 두가지 함수로 구현되어있음

https://donis-note.medium.com/django-rest-framework-authentication-permission-%EC%9D%B8%EC%A6%9D%EA%B3%BC-%EA%B6%8C%ED%95%9C-cc9b183fd901

profile
looooggi

0개의 댓글