Full Report
Django, a Python web framework, contains an Object Relational Mapper (ORM). This is a set of APIs for performing data storage that uses SQL under the hood but doesn't actually require the writing of SQL. There is a set of QuerySet methods that interact with an underlying database. From a security perspective, this is great because it should prevent SQL injection from the beginning. When interacting with the QuerySet methods, there are mandatory and optional parameters. An example QuerySet method is get(), which can be used with specific parameters. In Python, using the syntax func(**var) in a function call will treat var as a key/value pair where the key is the named parameter to use a particular value. After reviewing the code of the QuerySet APIs, they noticed that two parameters, _connector and _negated, were not being filtered adequately for SQL injection. The thing is, these aren't usually controllable values. The ability to set internal parameters to a function call is fine. But, this is where the **var syntax comes into play. If an attacker could control the contents of **var being used in one of the vulnerable functions, they can control the parameters vulnerable to SQL injection! They claim this can lead to authentication bypasses, data exfil and privilege escalation, which is true but context-dependent. This is labeled as critical with a CVSS score of 9.1. Personally, I find the post slightly exaggerated in terms of impact. Yes, there's a SQL injection (which is a good find), but how many applications follow the pattern above? Probably not a lot. Showing the impact of libraries is hard because there are no direct things at risk; it all depends on how people use them.
Analysis Summary
# Vulnerability: Critical SQL Injection in Django QuerySet APIs
## CVE Details
- **CVE ID:** CVE-2025-64459
- **CVSS Score:** 9.1 (Critical)
- **CWE:** CWE-89 (SQL Injection) / Improper Neutralization of Special Elements used in an SQL Command
## Affected Systems
- **Products:** Django Web Framework
- **Versions:**
- 6.0 (Beta versions)
- 5.2 (Versions prior to 5.2.8)
- 5.1 (Versions prior to 5.1.14)
- 4.2 (Versions prior to 4.2.26)
- Potentially older unsupported versions.
- **Configurations:** Applications that pass user-controlled input (e.g., `request.GET.dict()`) directly into QuerySet methods like `filter()`, `exclude()`, or `get()` using dictionary expansion (`**kwargs`).
## Vulnerability Description
Django's internal QuerySet logic uses specific internal parameters, `_connector` (determining AND/OR/XOR logic) and `_negated` (boolean inversion), to construct SQL queries. These parameters were not adequately filtered or validated when supplied through function calls.
By using Python’s `**var` syntax to pass a dictionary of user-provided data into a QuerySet method, an attacker can inject these internal parameters. This allows for the manipulation of the underlying SQL query logic, potentially changing the "WHERE" clause to bypass filters or access unauthorized records.
## Exploitation
- **Status:** PoC availability described; risk is context-dependent based on application code patterns.
- **Complexity:** Low (If the vulnerable dictionary expansion pattern exists).
- **Attack Vector:** Network (Remote).
## Impact
- **Confidentiality:** High (Unauthorized data exfiltration).
- **Integrity:** High (Potential for authentication bypass and privilege escalation).
- **Availability:** Low to Medium (Depending on the ability to disrupt query logic).
## Remediation
### Patches
Upgrade to the following versions:
- **Django 5.2.8**
- **Django 5.1.14**
- **Django 4.2.26**
### Workarounds
- **Input Validation:** Use Django Forms or Serializers to strictly validate and clean all user input.
- **Avoid Dictionary Expansion:** Do not pass `request.GET.dict()` or `request.POST.dict()` directly into QuerySet methods.
- **Whitelisting:** Explicitly map user-provided keys to allowed database fields rather than allowing arbitrary dictionary keys.
## Detection
- **Log Analysis:** Search web server access logs for requests containing the strings `_connector` or `_negated`.
- *Example:* `grep -i "_connector" /var/log/nginx/access.log`
- **Code Auditing:** Search the codebase for potentially vulnerable usage of dictionary expansion in database queries.
- *Example:* `grep -r "\.filter(\*\*" --include="*.py" .`
- **Behavioral Monitoring:** Monitor for unusual admin logins or unauthorized access to sensitive data objects.
## References
- **Vendor Advisory:** hxxps://www[.]djangoproject[.]com/weblog/2025/nov/05/security-releases/
- **Main Fix Commit:** hxxps://github[.]com/django/django/commit/98e642c69181c942d60a10ca0085d48c6b3068bb
- **Endor Labs Blog:** hxxps://www[.]endorlabs[.]com/learn/critical-sql-injection-vulnerability-in-django-cve-2025-64459