← Back to Django Course | Chapter 15: Security, Caching & Deployment | Lesson 5 of 9

ORM से SQL Injection Prevention

ORM एक translator जैसा है जो database से बात करने से पहले हमेशा पूछता है 'आपका exactly क्या मतलब है?', ताकि एक sneaky visitor एक search box के भेष में एक hidden command slip न कर सके।
Syntax
markup
# Safe: the ORM parameterizes values
ModelName.objects.filter(field=user_input)

# Raw SQL: pass values as parameters, never concatenate
ModelName.objects.raw('SELECT * FROM table WHERE field = %s', [user_input])

Unsafe तरीका: Raw String SQL

User input को सीधे एक SQL string में concatenate करना एक attacker को अपना खुद का SQL inject करने देता है। अगर username एक form से ' OR 1='1 के रूप में आया, तो query का meaning पूरी तरह बदल जाता है। इस pattern का कभी उपयोग नहीं किया जाना चाहिए।

Warning: यह example दिखाता है कि क्या NOT करना चाहिए -- यह SQL injection के लिए vulnerable है और सिर्फ comparison के लिए यहां है।

उदाहरण: The Unsafe Way: Raw String SQL

Concatenating user input directly into a SQL string lets an attacker inject their own SQL. If username came from a form as ' OR 1='1, the query's meaning changes completely. This pattern should never be used.

markup
# UNSAFE -- do not do this:
# query = "SELECT * FROM auth_user WHERE username = '" + username + "'"
# cursor.execute(query)
#
# If username is: ' OR '1'='1
# the query becomes true for every row in the table.
{# Django-only code -- models.py/views.py/urls.py/settings.py snippets, or template markup using Django template tags/variables -- can't run standalone via Judge0 or the browser preview, since it needs a real Django project. Only this course's pure-Python examples (example_lang == 'python', no Django imports) are actually runnable, so those still get the button below. #}

Safe तरीका: The ORM

Django के QuerySet methods जैसे .filter() कभी values को SQL text में directly insert नहीं करते। इसके बजाय, value database driver को एक separate parameter के रूप में pass की जाती है, इसलिए यह हमेशा plain data के रूप में treat होती है, SQL command के हिस्से के रूप में कभी नहीं।

Note: ORM default रूप से safe है -- यह protection आपको सिर्फ .filter() normally उपयोग करने से मिल जाती है।

उदाहरण: The Safe Way: The ORM

Django's QuerySet methods like .filter() never insert values directly into the SQL text. Instead, the value is passed as a separate parameter to the database driver, so it's always treated as plain data, never as part of the SQL command.

markup
from django.contrib.auth.models import User

# Safe: username is passed as a parameter, not concatenated
username = request.POST.get('username')
matches = User.objects.filter(username=username)
{# Django-only code -- models.py/views.py/urls.py/settings.py snippets, or template markup using Django template tags/variables -- can't run standalone via Judge0 or the browser preview, since it needs a real Django project. Only this course's pure-Python examples (example_lang == 'python', no Django imports) are actually runnable, so those still get the button below. #}

Parameterized Raw SQL, जब आपको चाहिए

कभी-कभी raw SQL unavoidable है। Django के .raw() और cursor.execute() एक separate parameters list के साथ %s placeholders support करते हैं, ORM जैसी same safety guarantee रखते हुए।

उदाहरण: Parameterized Raw SQL, When You Need It

Occasionally raw SQL is unavoidable. Django's .raw() and cursor.execute() support %s placeholders with a separate parameters list, keeping the same safety guarantee as the ORM.

markup
from django.db import connection

def find_user(username):
    with connection.cursor() as cursor:
        cursor.execute(
            'SELECT id, username FROM auth_user WHERE username = %s',
            [username],
        )
        return cursor.fetchone()
{# Django-only code -- models.py/views.py/urls.py/settings.py snippets, or template markup using Django template tags/variables -- can't run standalone via Judge0 or the browser preview, since it needs a real Django project. Only this course's pure-Python examples (example_lang == 'python', no Django imports) are actually runnable, so those still get the button below. #}
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
आम गलतियां
  1. User input को directly query text में concatenate करके raw SQL strings बनाना।
  2. Parameterized values के बजाय unescaped user input के साथ .raw() या .extra() उपयोग करना।
  3. यह मान लेना कि SQL injection Django में नहीं हो सकता क्योंकि 'ORM इसे handle करता है' जब project में कहीं और raw SQL उपयोग होता है।
चैप्टर सारांश
  • SQL injection तब होता है जब untrusted input directly एक SQL query string में insert किया जाता है और code के रूप में execute होता है।
  • Django का ORM अपने आप parameterized queries बनाता है, इसलिए values हमेशा query structure से separately send होती हैं।
  • User input के साथ .filter(), .exclude(), और दूसरे ORM methods उपयोग करना default रूप से safe है।
  • Raw SQL सिर्फ तब safe है जब parameters separately pass किए जाएं, कभी query में string-formatted नहीं।

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.