Django

⌘K
  1. Home
  2. Django
  3. Django তে কিভাবে কাজ করতে...
  4. middleware
  5. ৭. Django-র CSRF Middleware সম্পর্কে বিস্তারিত

৭. Django-র CSRF Middleware সম্পর্কে বিস্তারিত

CSRF কী এবং কীভাবে Cross-Site Request Forgery আক্রমণ কাজ করে?


CSRF বা Cross-Site Request Forgery একটি সাধারণ ও বিপজ্জনক ওয়েব অ্যাটাক, যেখানে হ্যাকার ব্যবহারকারীর অননুমোদিত অ্যাকশনের সুবিধা নেয়। এই আক্রমণের মাধ্যমে হ্যাকার ব্যবহারকারীর লগইন সেশনের মাধ্যমে একটি অবৈধ রিকোয়েস্ট পাঠাতে পারে।

Cross-Site Request Forgery (CSRF) একটি ধরনের আক্রমণ যেখানে হ্যাকার একজন ব্যবহারকারীর ব্রাউজারের মাধ্যমে ম্যালিশাস রিকোয়েস্ট পাঠায়, যার ফলে ব্যবহারকারী অজান্তে তাদের অনুমতি ছাড়া কিছু করতে পারে। সাধারণত, এটি ঘটে যখন ব্যবহারকারী ইতিমধ্যে একটি সাইটে লগইন থাকে এবং হ্যাকার সেই সেশনের মাধ্যমে একটি অননুমোদিত রিকোয়েস্ট পাঠায়।

কেন Middleware-এ CSRF ব্যবহৃত হয়?

Middleware-এ CSRF টোকেন ভেরিফিকেশন থাকার ফলে রিকোয়েস্টটি প্রকৃত ব্যবহারকারী দ্বারা পাঠানো হয়েছে কিনা নিশ্চিত করা যায়। এই সিস্টেম ব্যবহারকারীর ব্রাউজারে নির্দিষ্ট একটি টোকেন তৈরি করে এবং এই টোকেন ছাড়া POST রিকোয়েস্ট গ্রহণ করা হয় না।

CSRF আক্রমণের বাস্তব উদাহরণ:


ধরা যাক, শুভ নামে একজন ব্যবহারকারী একটি ফোরাম ওয়েবসাইট ব্যবহার করছেন, যেমন www.example.com। তিনি এই সাইটে একটি পোস্ট তৈরি করতে লগইন করেছেন। ফোরাম সাইটটি একটি সেশন কুকি তৈরি করেছে যাতে শুভ যখনই ফোরাম সাইটে কিছু করেন, সেই রিকোয়েস্টগুলো শুভর অ্যাকাউন্টের অধীনে তৈরি হয়।

এদিকে, এক হ্যাকার একটি ম্যালিশাস ওয়েবসাইট তৈরি করে যেখানে একটি গোপন ফর্ম রয়েছে। এই ফর্মটি স্বয়ংক্রিয়ভাবে একটি POST রিকোয়েস্ট পাঠায় শুভর ফোরাম সাইটে, যাতে শুভর অ্যাকাউন্ট ব্যবহার করে একটি অননুমোদিত পোস্ট তৈরি করা যায়।

কিভাবে আক্রমণ ঘটে

শুভ একটি লিঙ্কে ক্লিক করেন যা তাকে হ্যাকার তৈরি করা ওয়েবসাইটে নিয়ে যায়। এই ওয়েবসাইটটি স্বয়ংক্রিয়ভাবে একটি POST ফর্ম সাবমিট করে যা শুভর ফোরাম সাইটে একটি পোস্ট তৈরি করার নির্দেশ দেয়। যেহেতু শুভ আগে থেকেই লগইন করা অবস্থায় আছেন, ব্রাউজার সেই রিকোয়েস্টের সাথে শুভর সেশন কুকিও পাঠিয়ে দেয়।

উদাহরণ কোড: ম্যালিশাস ফর্ম

<!-- Malicious Website -->
<html>
<body>
    <h1>Surprise! You're hacked!</h1>
    <form id="csrf-form" action="https://www.example.com/new-post" method="POST">
        <input type="hidden" name="title" value="Hacked by Hacker">
        <input type="hidden" name="content" value="This post was created by a CSRF attack!">
    </form>
    <script>
        document.getElementById('csrf-form').submit(); // Automatically submits the form
    </script>
</body>
</html>

আক্রমণের ফলাফল

ফোরাম সাইট, www.example.com, রিকোয়েস্টটি গ্রহণ করে এবং শুভর সেশন কুকি থাকার কারণে রিকোয়েস্টটিকে বৈধ মনে করে। ফলে, শুভর অ্যাকাউন্টে একটি নতুন পোস্ট তৈরি হয়: “Hacked by Hacker” শিরোনামে, যা তিনি নিজে তৈরি করেননি।


Django-তে CSRF Middleware কীভাবে কাজ করে তার সাধারণ ধারণা


Django-তে CSRF Middleware যুক্ত করা আছে যা প্রতিটি POST রিকোয়েস্টে একটি CSRF টোকেন যাচাই করে। Django CSRF Middleware কীভাবে কাজ করে তা সংক্ষেপে নিচে বর্ণনা করা হলো:

  1. Token Generation: যখন একটি ফর্ম লোড করা হয়, Django ফর্মের জন্য একটি CSRF Token তৈরি করে। এই টোকেনটি সাধারণত HTML ফর্মের মধ্যে {% csrf_token %} ট্যাগের মাধ্যমে hidden ইনপুট হিসেবে রাখা হয়।
  2. Token Validation: ব্যবহারকারী যখন ফর্ম সাবমিট করেন, সেই ফর্মের hidden ফিল্ডে থাকা CSRF টোকেনটি POST রিকোয়েস্টের সাথে পাঠানো হয়। Django তখন এই টোকেনটি যাচাই করে চেক করে যে এটি সঠিক কিনা।
  3. Token Matching: রিকোয়েস্টের সাথে থাকা CSRF টোকেনটি Django এর সিস্টেমে থাকা টোকেনের সাথে মিলে গেলে তা গ্রহণ করা হয়, অন্যথায় 403 Forbidden Error রিটার্ন করে।
  4. Request Protection: Django CSRF Middleware শুধুমাত্র POST, PUT, DELETE ইত্যাদি রিকোয়েস্টগুলোতে CSRF টোকেন যাচাই করে, কারণ এই ধরনের রিকোয়েস্টে ডেটা পরিবর্তন করার সম্ভাবনা থাকে। GET রিকোয়েস্ট সাধারণত CSRF টোকেন যাচাই ছাড়া অনুমোদন পায়।

Django CSRF কুকি কীভাবে কাজ করে?

Django একটি CSRF কুকি তৈরি করে, যা সাধারণত csrftoken নামে পরিচিত। এই কুকিটি তৈরি হয় Django-এর এক ক্রিপ্টোগ্রাফিক ফাংশন (যেমন, get_random_string()) ব্যবহার করে, এবং এটি খুবই ইউনিক এবং প্রায়ই অনুমান করা বা ভাঙা কঠিন।

কুকি তৈরির প্রক্রিয়া

১. ফর্ম বা প্রথম রিকোয়েস্টে কুকি সেটআপ: যখন কোনো ভিজিটর Django সাইটে ফর্ম লোড করে বা কোনো ভিউতে প্রথমবার প্রবেশ করে যা CSRF সুরক্ষিত, তখন Django সেই ভিজিটরের ব্রাউজারে csrftoken নামে একটি কুকি সেট করে।

২. টোকেনের বৈধতা এবং সেশন: এই টোকেনটি সাধারণত সেশন-নির্ভর হয় না, যা মানে হলো, ব্যবহারকারী লগইন বা লগআউট করলেও এটি পরিবর্তন হয় না। Django এটি শুধুমাত্র তখন পরিবর্তন করে যখন: – ব্রাউজারে কুকির মেয়াদ শেষ হয় বা কুকিটি ম্যানুয়ালি মুছে ফেলা হয়। – কোনো বিশেষ সুরক্ষার জন্য SESSION_COOKIE_AGE বা CSRF_COOKIE_AGE সেটিংস পরিবর্তিত হয়।

৩. প্রতিটি রিকোয়েস্টে একই কুকি ব্যবহার: CSRF কুকি একবার তৈরি হলে Django ফর্মগুলোয় {% csrf_token %} ট্যাগ ব্যবহার করে সেই একই কুকি পাঠায়। এভাবে Django প্রতি রিকোয়েস্টে ফর্মের সাথে একই CSRF টোকেন পাঠায়, যা সার্ভার পরে যাচাই করে।

কুকি কখন নষ্ট হয়?

১. কুকি নিজে নিজেই মেয়াদ শেষ হলে: CSRF_COOKIE_AGE সেটিং ব্যবহার করে Django কুকির মেয়াদ নির্ধারণ করে। ডিফল্ট মেয়াদ এক বছরের জন্য নির্ধারিত থাকে।

২. ম্যানুয়ালি কুকি মুছে ফেলা হলে: ব্যবহারকারী ব্রাউজারের কুকি ম্যানুয়ালি মুছে ফেললে, পরবর্তী ফর্ম লোডের সময় Django একটি নতুন কুকি প্রদান করে।

৩. নতুন সেশন শুরু হলে (কিছু নির্দিষ্ট ক্ষেত্রে): নির্দিষ্ট কিছু কনফিগারেশনে (যেমন, SESSION_COOKIE_AGE) সেশন শেষ হলে Django নতুন CSRF কুকি তৈরি করতে পারে।

CSRF সুরক্ষা নিশ্চিত করতে কী করা উচিত

একজন ডেভেলপার হিসেবে নিচের সুরক্ষা ব্যবস্থা নিয়ে নিশ্চিত থাকা জরুরি:

১. HTTPS নিশ্চিত করা: সর্বদা প্রোডাকশনে HTTPS ব্যবহার করুন এবং CSRF_COOKIE_SECURE = TrueSESSION_COOKIE_SECURE = True সেট করুন।

২. HTTPOnly অ্যাট্রিবিউট: XSS আক্রমণ প্রতিরোধে CSRF_COOKIE_HTTPONLY = True সেট করতে পারেন যদি JavaScript-এ টোকেন ব্যবহার করতে না হয়।

৩. Content Security Policy (CSP) ব্যবহার: Django-তে django-csp প্যাকেজ ব্যবহার করে CSP সেট করতে পারেন যা JavaScript-ভিত্তিক XSS আক্রমণ থেকে রক্ষা করতে সাহায্য করে।

৪. JavaScript থেকে সরাসরি কুকি অ্যাক্সেস করা এড়ানো: AJAX বা API কলের ক্ষেত্রে CSRF টোকেন সরাসরি {% csrf_token %} ট্যাগ ব্যবহার করে পাঠানো উচিত এবং X-CSRFToken হেডার সেট করা উচিত।

৫. সময়মতো কুকি পরিষ্কার করা: অনেক দিন ব্যবহৃত কুকি ঝুঁকি সৃষ্টি করতে পারে, তাই নির্দিষ্ট সময় অন্তর কুকি রিফ্রেশ বা মেয়াদ শেষ করে নতুন টোকেন তৈরি করা যায়।

৬. CSRF টোকেন যাচাই ছাড়া API এড়ানো: CSRF ব্যতীত কিছু ভিউতে @csrf_exempt ডেকোরেটর ব্যবহার করা থেকে বিরত থাকুন।

কিভাবে প্রটেক্ট করবেন

কল্পনা করুন, আপনি Django REST API তৈরি করছেন যেখানে CSRF সুরক্ষা অত্যন্ত গুরুত্বপূর্ণ। আপনি ফ্রন্টএন্ড থেকে JavaScript ব্যবহার করে একটি POST রিকোয়েস্ট করতে চান যা CSRF সুরক্ষিত থাকবে।

  • ফ্রন্টএন্ড থেকে CSRF টোকেন পাঠানো:
fetch("/your-endpoint/", {
    method: "POST",
    headers: {
        "X-CSRFToken": getCookie("csrftoken")
    },
    body: JSON.stringify(data)
});
  • Django টেমপ্লেটে {% csrf_token %} ট্যাগ ব্যবহার করে CSRF টোকেন যুক্ত করা

    Django টেমপ্লেটের ফর্মগুলিতে {% csrf_token %} ট্যাগ ব্যবহার করা খুবই সহজ। {% csrf_token %} ট্যাগটি ফর্মের মধ্যে hidden ইনপুট ফিল্ড হিসেবে একটি CSRF টোকেন যোগ করে যা POST রিকোয়েস্টে পাঠানো হয়। এই টোকেনটি Django সার্ভার যাচাই করে এবং নিশ্চিত করে যে ফর্মটি বৈধ।

    উদাহরণ:

    <form method="post" action="/submit-form/">
        {% csrf_token %}
        <input type="text" name="username" placeholder="Username">
        <button type="submit">Submit</button>
    </form>
    

    উপরের কোডে {% csrf_token %} Django একটি hidden ইনপুট ফিল্ড তৈরি করে যা দেখতে কিছুটা এই রকম হতে পারে:

    <input type="hidden" name="csrfmiddlewaretoken" value="gFb4S3kWv1bL9jUcTqY9rKt6">
    

    এই hidden ইনপুট ফিল্ডে CSRF টোকেন থাকে যা Django অটোমেটিক্যালি রিকোয়েস্টের সাথে যাচাই করে।


    • AJAX এবং JavaScript দিয়ে CSRF টোকেন প্রয়োগ করার পদ্ধতি

    AJAX রিকোয়েস্টের জন্য CSRF টোকেন যোগ করা কিছুটা ভিন্ন হয়। কারণ AJAX রিকোয়েস্টে সাধারণত ফর্ম সাবমিশনের মতো সরাসরি hidden ইনপুট ফিল্ড থাকে না। তাই JavaScript বা jQuery ব্যবহার করে CSRF টোকেন ম্যানুয়ালি যোগ করতে হয়।

    jQuery এবং AJAX এর উদাহরণ:

    Django কুকি থেকে CSRF টোকেন খুঁজে বের করে AJAX রিকোয়েস্টের হেডারে যোগ করা যায়। উদাহরণস্বরূপ:

    // কুকি থেকে CSRF টোকেন পাওয়ার ফাংশন
    function getCookie(name) {
        let cookieValue = null;
        if (document.cookie && document.cookie !== '') {
            const cookies = document.cookie.split(';');
            for (let i = 0; i < cookies.length; i++) {
                const cookie = cookies[i].trim();
                if (cookie.substring(0, name.length + 1) === (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    }
    
    // AJAX রিকোয়েস্টের সাথে CSRF টোকেন যোগ করা
    const csrftoken = getCookie('csrftoken');
    
    $.ajaxSetup({
        headers: { "X-CSRFToken": csrftoken }
    });
    
    $.ajax({
        url: "/submit-data/",
        type: "POST",
        data: { "username": "test_user" },
        success: function(response) {
            console.log("Data submitted successfully!");
        }
    });
    

    এখানে getCookie() ফাংশন কুকি থেকে csrftoken বের করে এবং $.ajaxSetup() দ্বারা AJAX রিকোয়েস্টের সাথে CSRF টোকেন যোগ করে।

    HTTPS এ থাকা: Django সাইটটি অবশ্যই HTTPS এ থাকবে যাতে CSRF_COOKIE_SECURE এর মাধ্যমে কেবল নিরাপদ কুকি পাঠানো হয়।

    Django সেটিংস সুরক্ষিত করা:

    # settings.py
    CSRF_COOKIE_SECURE = True
    SESSION_COOKIE_SECURE = True
    CSRF_COOKIE_HTTPONLY = True
    CSRF_COOKIE_SAMESITE = 'Lax'
    

    Django-তে CSRF Exception Handling এবং Bypassing Techniques

    Django-তে CSRF Exception Handling এবং Bypassing Techniques প্রয়োজনীয় হতে পারে বিশেষ পরিস্থিতিতে, যেমন কিছু API endpoint-এ বা trusted রিকোয়েস্টে, যেখানে CSRF টোকেন যাচাই প্রয়োজন নয়। তবে এই bypassing অপশনগুলি ব্যবহারে সতর্কতা প্রয়োজন, কারণ সঠিকভাবে ব্যবহৃত না হলে এগুলো নিরাপত্তা ঝুঁকি তৈরি করতে পারে। নিচে csrf_exceptioncsrf_exempt এর ব্যাখ্যা এবং ব্যবহার বিধি দেওয়া হলো।


    ১. csrf_exempt কী এবং কেন ব্যবহার করা হয়

    csrf_exempt Django-র একটি ডেকোরেটর যা নির্দিষ্ট ভিউ বা API endpoint-এ CSRF টোকেন যাচাই অক্ষম করতে ব্যবহৃত হয়। এটি মূলত সেসব ক্ষেত্রে প্রযোজ্য, যেখানে:

    • External API Calls: বাহ্যিক পরিষেবাগুলি Django-র CSRF টোকেন জানে না, তাই এ ধরনের endpoint-এ CSRF যাচাই না করাও যুক্তিসঙ্গত।
    • Trusted Clients: নির্দিষ্ট, নির্ভরযোগ্য ক্লায়েন্ট থেকে অনুরোধ আসছে বলে নিশ্চিত হলে।

    ব্যবহার:

    from django.views.decorators.csrf import csrf_exempt
    from django.http import JsonResponse
    
    @csrf_exempt
    def my_view(request):
        if request.method == "POST":
            # POST রিকোয়েস্ট প্রক্রিয়া
            return JsonResponse({"message": "CSRF টোকেন ছাড়াই POST রিকোয়েস্ট সফল হয়েছে।"})
        return JsonResponse({"error": "Only POST requests allowed."})
    

    csrf_exempt ব্যবহারের নিরাপত্তা ঝুঁকি

    • Cross-Site Request Forgery Vulnerability: csrf_exempt ব্যবহার করা হলে, view-এর জন্য Django CSRF সুরক্ষা অক্ষম করে। এটি আক্রমণকারীদের অনুমতি দেয় একই ওয়েবসাইটের বাহির থেকে মালিশিয়াস POST রিকোয়েস্ট পাঠাতে।
    • Malicious Requests Handling: ভুলভাবে csrf_exempt ব্যবহার করা হলে অ্যাপ্লিকেশনটি অনিরাপদ হতে পারে, কারণ বাহ্যিক অনির্ভরযোগ্য সাইট থেকেও রিকোয়েস্ট আসতে পারে যা CSRF যাচাই বাদ দিয়ে অ্যাপ্লিকেশনের ক্ষতি করতে পারে।

    ৩. কখন csrf_exempt ব্যবহার করা যেতে পারে

    csrf_exempt শুধু সেসব পরিস্থিতিতে ব্যবহার করুন যেখানে এটি অপরিহার্য এবং অন্যান্য নিরাপত্তা ব্যবস্থাপনা নিশ্চিত করা হয়েছে। উদাহরণস্বরূপ:

    • Public API Endpoints: যেখানে শুধুমাত্র trusted sources বা নির্দিষ্ট users কে ডাটা প্রদানে অনুমোদিত। API token বা OAuth দিয়ে নিরাপত্তা নিশ্চিত করতে পারেন।
    • Webhook Endpoints: বাহ্যিক সার্ভিস থেকে ডেটা গ্রহণের জন্য ব্যবহৃত হয় এবং সাধারণত নির্ভরযোগ্য ও পরিচিত উৎস থেকে আসে।

    বিশেষ সতর্কতা:

    • API বা webhook ব্যবহারের ক্ষেত্রে authenticationauthorization প্রয়োগ করে অতিরিক্ত সুরক্ষা নিশ্চিত করতে হবে।
    • যথাসম্ভব POST রিকোয়েস্টগুলিকে নিরাপত্তা মেনে কার্যকর করতে হবে।

    ৪. কিছু নির্দিষ্ট ভিউ বা API Endpoint-এ CSRF ব্যতীত POST রিকোয়েস্ট অনুমোদন

    কিছু নির্দিষ্ট API Endpoint-এ CSRF যাচাই এড়িয়ে যাওয়া দরকার হলে, csrf_exempt ব্যবহার করতে পারেন। তবে এটি ব্যবহারের সময় সতর্ক থাকতে হবে এবং প্রয়োজনীয় অন্যান্য সুরক্ষা ব্যবস্থা নিতে হবে।

    উদাহরণস্বরূপ:

    # views.py
    from django.views.decorators.csrf import csrf_exempt
    from django.http import JsonResponse
    from django.views import View
    
    @csrf_exempt
    def public_api_endpoint(request):
        if request.method == "POST":
            # Trusted source থেকে ডাটা সংগ্রহ করুন
            return JsonResponse({"message": "This is a public endpoint without CSRF check."})
        return JsonResponse({"error": "Only POST requests are allowed."})
    

    এ ধরনের endpoint-এ, API token-based authentication বা OAuth ব্যবহার করা উচিত যাতে বাহ্যিক অ্যাক্সেস নিয়ন্ত্রণে থাকে এবং শুধুমাত্র নির্দিষ্ট বা trusted clients POST রিকোয়েস্ট করতে পারে।

    CSRF সিকিউরিটি অডিট চেকলিস্ট

    প্রোডাকশন ডেপ্লয়মেন্টের সময় Django প্রজেক্টে CSRF সুরক্ষা নিশ্চিত করার জন্য নিম্নোক্ত চেকলিস্টটি ফলো করা উচিত।

    1. HTTPS এনাবল করা: প্রোডাকশনে সর্বদা HTTPS ব্যবহার করুন।
    2. CSRF কনফিগারেশন যাচাই: CSRF_COOKIE_SECURE, CSRF_COOKIE_HTTPONLY, এবং CSRF_COOKIE_SAMESITE ঠিকঠাকভাবে কনফিগার করা হয়েছে কিনা তা নিশ্চিত করুন।
    3. Custom CSRF_COOKIE_NAME ব্যবহার: নিরাপত্তার জন্য কাস্টম কুকি নাম ব্যবহার করা যেতে পারে।
    4. AJAX রিকোয়েস্টের ক্ষেত্রে CSRF হেডার চেক: JavaScript রিকোয়েস্টে X-CSRFToken হেডার যুক্ত করতে ভুলবেন না।
    5. ফ্রেম অপশন কনফিগার করা: X-Frame-Options কনফিগার করুন ক্লিকজ্যাকিং আক্রমণ প্রতিরোধে।
    6. HSTS এনাবল করা: SECURE_HSTS_SECONDS এবং অন্যান্য HSTS অপশন কনফিগার করুন।
    7. Content Security Policy (CSP) সেটআপ: django-csp ব্যবহার করে CSP কনফিগার করে XSS আক্রমণ প্রতিরোধ করুন।
    8. csrf_exempt এড়িয়ে চলা: শুধুমাত্র বিশেষ প্রয়োজন হলে নির্দিষ্ট ভিউতে csrf_exempt ব্যবহার করুন।
    9. CORS কনফিগার করা: প্রোডাকশন অ্যাপ্লিকেশনে CORS ঠিকঠাকভাবে সেট করা আছে কিনা তা যাচাই করুন।
    10. Test Security Headers: https://securityheaders.com/ এ গিয়ে আপনার সাইটের সিকিউরিটি হেডার টেস্ট করুন।

    How can we help?