CVE-2022-28346

9.8 CRITICAL

📋 TL;DR

This SQL injection vulnerability in Django allows attackers to execute arbitrary SQL commands through crafted dictionary parameters in QuerySet methods. It affects Django applications using annotate(), aggregate(), or extra() methods with dictionary expansion. All Django deployments using vulnerable versions are affected.

💻 Affected Systems

Products:
  • Django
Versions: Django 2.2 before 2.2.28, 3.2 before 3.2.13, 4.0 before 4.0.4
Operating Systems: All
Default Config Vulnerable: ⚠️ Yes
Notes: Only affects applications using QuerySet.annotate(), aggregate(), or extra() methods with dictionary expansion (**kwargs).

📦 What is this software?

⚠️ Risk & Real-World Impact

🔴

Worst Case

Full database compromise including data theft, modification, deletion, and potential remote code execution via database functions.

🟠

Likely Case

Data exfiltration, privilege escalation, and application compromise through SQL injection.

🟢

If Mitigated

Limited impact with proper input validation and database user privilege restrictions.

🌐 Internet-Facing: HIGH
🏢 Internal Only: MEDIUM

🎯 Exploit Status

Public PoC: ⚠️ Yes
Weaponized: LIKELY
Unauthenticated Exploit: ✅ No
Complexity: LOW

Exploitation requires attacker to control dictionary parameters passed to vulnerable methods. Public proof-of-concept exists in security advisories.

🛠️ Fix & Mitigation

✅ Official Fix

Patch Version: Django 2.2.28, 3.2.13, 4.0.4

Vendor Advisory: https://docs.djangoproject.com/en/4.0/releases/security/

Restart Required: Yes

Instructions:

1. Identify Django version: python -m django --version
2. Upgrade to patched version: pip install Django==2.2.28 OR Django==3.2.13 OR Django==4.0.4
3. Restart all Django processes and web servers
4. Test application functionality

🔧 Temporary Workarounds

Input Validation Wrapper

all

Create wrapper functions that validate dictionary keys before passing to vulnerable methods

# Python code to validate dictionary keys
# Ensure keys contain only alphanumeric characters and underscores
import re

def safe_annotate(queryset, **kwargs):
    for key in kwargs.keys():
        if not re.match(r'^[a-zA-Z_][a-zA-Z0-9_]*$', key):
            raise ValueError(f'Invalid alias: {key}')
    return queryset.annotate(**kwargs)

🧯 If You Can't Patch

  • Implement strict input validation for all dictionary parameters passed to QuerySet methods
  • Apply database-level controls: use minimal privilege database users, enable query logging, implement WAF rules

🔍 How to Verify

Check if Vulnerable:

Check Django version: python -m django --version. If version is 2.2.x < 2.2.28, 3.2.x < 3.2.13, or 4.0.x < 4.0.4, system is vulnerable.

Check Version:

python -m django --version

Verify Fix Applied:

After upgrade, verify version shows patched version (2.2.28, 3.2.13, or 4.0.4). Test application functionality with known safe inputs.

📡 Detection & Monitoring

Log Indicators:

  • Unusual SQL queries in Django logs
  • Database error logs showing malformed SQL
  • Unexpected database operations

Network Indicators:

  • Unusual database connection patterns
  • Large data transfers from database

SIEM Query:

source="django.log" AND ("annotate" OR "aggregate" OR "extra") AND error OR source="database.log" AND sql_injection

🔗 References

📤 Share & Export