CSRF Token trong Django là gì?

CSRF Token sẽ bảo vệ web của bạn khỏi lỗ hổng bảo mật phổ biến. Dưới đây là những điều bạn cần biết về CSRF Token trong Django.

Django

Django là một framework web của Python mà bạn có thể dùng để xây dựng các ứng dụng web bảo mật. Nó cung cấp nhiều tính năng giúp lập trình viên xây dựng bảo mật. Một trong số đó là CSRF token. Về cơ bản, nó bảo vệ các biểu mẫu khỏi những cuộc tấn công Cross-Site Request Forgery (kỹ thuật tấn công giả mạo chính chủ thể).

CSRF Token là gì?

Một token CSRF là tính năng bảo vệ ứng dụng web khỏi các cuộc tấn công giả mạo. Nó cho phép server ứng dụng kiểm tra xem một biểu mẫu được gửi từ trình duyệt thực sự hay do hacker giả mạo.

CSRF token là các trường nhập biểu mẫu, giúp theo dõi phiên hoạt động của người dùng. Một framework ứng dụng web phía server thường tạo token CSRF cho từng phiên người dùng độc đáo. Server này kiểm tra xem liệu token có chính xác bất cứ khi nào người dùng gửi biểu mẫu. Token CSRF thường bao gồm các chuỗi và số ngẫu nhiên, khiến giá trị của chúng khó dự đoán.

Tạo CSRF Token trong Django

Hàm get_token() của Django tạo ngẫu nhiên token CSRF. Để tìm hàm này, điều hướng tới file csrf.py bên trong môi trường ảo của Python. Cấu trúc thư mục trông sẽ như sau:

env/

└── Lib/

    └── site-packages/

        └── django/

            └── middleware/

                └── csrf.py

Bên trong file này, bạn bạn sẽ thấy hàm get_token(), trả về token này. Django dùng data masking (mặt nạ dữ liệu) để bảo vệ giá trị của token khỏi hacker.

Mặc định, Django cho phép bảo vệ CSRF cho trang bằng cách thêm django.middleware.csrf.CsrfViewMiddleware trong danh sách MIDDLEWARE của file settings.py. Toàn bộ việc bạn cần làm là thêm {% csrf_token %} vào biểu mẫu POST. Nếu không thêm {% csrf_token %}, bạn sẽ gặp lỗi 403 (forbidden) khi gửi biểu mẫu.

403 (forbidden)

Khi thêm {% csrf_token %} vào biểu mẫu của bạn, nó tự động tạo một trường nhập ẩn kèm tên csrfmiddlewaretoken, chứa giá trị của token CSRF. Server dùng giá trị này để xác định xem việc gửi biểu mẫu có đúng hay không. Bạn có thể kiểm tra giá trị của trường ẩn bằng cách xem nguồn trang hoặc dùng tính năng công cụ lập trình viên của trình duyệt.

Phương thức POST

Cách token CSRF hoạt động trong Django

Khi mở trang bằng biểu mẫu này, Django tự động tạo một cookie trình duyệt tên csrftoken. Cookie này liên tục theo dõi hoạt động người dùng trên trang và nhận diện riêng từng người.

Khi người dùng gửi biểu mẫu, server này so sánh giá trị của cookie với giá trị của csrfmiddlewaretoken trong trường nhập bị ẩn. Nếu những giá trị này trùng khớp, server sẽ xử lý biểu mẫu thành công, nếu không, quá trình này sẽ phát sinh lỗi.

Thoạt nhìn, giá trị của cookie và csrfmiddlewaretoken hiện khác nhau. Điều này là có chủ ý và bổ sung thêm một lớp bảo vệ cho mã thông báo CSRF. Mã thông báo CSRF được so sánh với cookie như sau:

  • Hàm get_token() che mã thông báo CSRF trước khi chuyển nó vào trường nhập liệu.
  • Khi biểu mẫu được gửi, token CSRF sẽ được hiển thị với sự trợ giúp của khóa bí mật trong file cài đặt.
  • Token được bỏ che được so sánh với cookie phiên.
  • Nếu giá trị giống nhau, biểu mẫu sẽ được xử lý. Nếu không, server trả về một lỗi.

Để ngăn hacker đánh cắp token CSRF, Django làm mới nó mỗi lần khởi động một phiên người dùng.

CSRF Token

Tạo token CSRF tùy chỉnh

Dù Django làm token CSRF bảo vệ biểu mẫu dễ dàng bằng cách chỉ thêm {% csrf_token %}, bạn vẫn có thể tạo token CSRF và thêm chúng vào biểu mẫu theo cách thủ công. Để làm việc này, nhập hàm get_token():

from django.middleware.csrf import get_token

Trong cửa sổ xem, bạn có thể tạo token CSRF như sau:

def view_name(request):
    csrf_token = get_token(request)

    # perform view logic
    context = {
        "csrf_token": csrf_token
    }

    return render(request, 'app_name/template.html', context=context)

Trong mẫu HTML, bạn có thể bao gồm tag nhập và thêm csrf_token vào nó như thế này:

<form method="POST" >
    <input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}">
    {{form.as_p}}
    <button type="submit" class="btn btn-outline-secondary">Add Book</button>
</form>

Ngoài ra, bạn có thể tạo trường nhập ẩn từ các cửa sổ xem như sau:

def your_view(request):
    csrf_token = get_token(request)
    csrf_token_html = '<input type="hidden" name="csrfmiddlewaretoken" value="{}" />'.format(csrf_token)

    # perform view logic
    context = {
        "csrf_token": csrf_token_html
    }

    return render(request, 'app_name/template.html', context=context)

Sau đó, bạn có thể thêm nó vào mẫu HTML như thế này:

<form method="POST" >
    {{ csrf_token_html|safe }}
    {{form.as_p}}
    <button type="submit" class="btn btn-outline-secondary">Add Book</button>
</form>

Nếu muốn kiểm soát hoàn toàn bảo vệ CSRF của biểu mẫu, bạn có thể so sánh token CSRF với cookie được lưu trong trình duyệt. Dựa trên kết quả so sánh, bạn có thể xử lý việc gửi biểu mẫu như ý muốn. Ví dụ:

from django.shortcuts import render
from django.middleware.csrf import get_token, _unmask_cipher_token
from django.utils.crypto import constant_time_compare

def your_view(request):
    # Tạo token CSRF tùy biến
    csrf_token = get_token(request)
    csrf_cookie = request.COOKIES.get('csrftoken')

    # unmask csrf token
    unmasked_csrf_token = _unmask_cipher_token(csrf_token)
    
    # So sánh các token
    if not constant_time_compare(unmasked_csrf_token, csrf_cookie):
        # Xử lý trường hợp token không trùng khớp
              pass
    else:
        # Xử lý trường hợp token trùng khớp
        pass
    # Tạo mẫu
    context = {
        'csrf_token': csrf_token,
    }

    return render(request, 'app_name/template.html', context=context)

Đoạn mã này truy xuất csrf_cookie từ đối tượng yêu cầu HTTP. Sau đó, nó sử dụng hàm _unmask_cipher_token() để mở csrf_token.

Một câu lệnh có điều kiện so sánh các giá trị của csrf_cookie được truy xuất và csrf_token bị lộ. So sánh này sử dụng hàm constant_time_compare để bảo vệ chống lại việc khai thác thời gian. Bạn có thể viết logic của mình dựa trên kết quả so sánh.

Trên đây là những điều bạn cần biết về CSRF token trong Django. Hi vọng bài viết hữu ích với các bạn.

Thứ Sáu, 05/05/2023 14:36
3,52 👨 827
0 Bình luận
Sắp xếp theo