CVE-2024-53908
Executive Summary
CVE-2024-53908 is a critical SQL injection vulnerability affecting Django's HasKey database lookup when used with Oracle databases. The flaw exists in the django.db.models.fields.json.HasKey lookup, allowing an attacker to inject arbitrary SQL if untrusted data is passed as the left-hand side (lhs) value. This vulnerability impacts Django versions 5.1 before 5.1.4, 5.0 before 5.0.10, and 4.2 before 4.2.17. The CVSS score is 0.0 due to incomplete NVD data, but based on the nature of the vulnerability, it is assessed as critical with a vector of AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H. No public proof-of-concept (PoC) or exploit code is available at this time. Immediate patching 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
Django is a widely used Python web framework distributed via PyPI. This vulnerability affects the core framework itself, not a third-party package. Organizations using Django with Oracle databases should treat this as a high-priority supply chain risk. Verify your Django version and update immediately. Monitor for any malicious packages that may attempt to exploit this vulnerability in the wild.
CVSS Breakdown & Threat Level
While the NVD CVSS score is 0.0, a more accurate assessment based on the vulnerability's characteristics is:
- Attack Vector (AV): Network (N) – The vulnerability can be exploited remotely.
- Attack Complexity (AC): Low (L) – No special conditions are required.
- Privileges Required (PR): None (N) – No authentication needed.
- User Interaction (UI): None (N) – No user action required.
- Scope (S): Unchanged (U) – The vulnerable component and the impacted component are the same.
- Confidentiality (C): High (H) – Full database read access possible.
- Integrity (I): High (H) – Full database write access possible.
- Availability (A): High (H) – Potential for denial of service or data destruction.
Threat Level: Critical. The ability to inject SQL without authentication makes this a severe risk for any Django application using Oracle.
Deep Dive & Mechanics
The vulnerability resides in the HasKey lookup, which is used to check for the existence of a key in a JSON field. When used directly (e.g., MyModel.objects.filter(json_field__has_key=user_input)), the lhs (left-hand side) value is not properly sanitized before being incorporated into the SQL query. On Oracle databases, this unsanitized input can be used to break out of the intended SQL syntax and execute arbitrary commands.
The issue is specific to Oracle because of how Django constructs the SQL for the HasKey lookup on that platform. The lhs is concatenated into a JSON_EXISTS or similar function call without proper parameterization. An attacker can provide a crafted lhs value that includes SQL metacharacters, leading to injection.
The __ (double underscore) syntax (e.g., MyModel.objects.filter(json_field__has_key='some_key')) is not affected because Django handles the key extraction safely in that path.
Vulnerable vs. Patched Code
Vulnerable Code (Django < 4.2.17, < 5.0.10, < 5.1.4):
In the Oracle backend, the HasKey lookup is implemented by directly interpolating the lhs into a SQL string. For example:
# django/db/models/lookups.py (simplified)
class HasKey(PostgresOperatorLookup):
# ...
def as_oracle(self, compiler, connection):
lhs, lhs_params = self.process_lhs(compiler, connection)
rhs, rhs_params = self.process_rhs(compiler, connection)
# VULNERABLE: lhs is directly concatenated
return "JSON_EXISTS(%s, '$.%s')" % (lhs, rhs), lhs_params + rhs_params
The lhs is not escaped or parameterized, allowing injection.
Patched Code (Django 4.2.17, 5.0.10, 5.1.4):
The fix ensures that the lhs is properly quoted or parameterized. The patched version uses a safe wrapper or parameterized query:
# django/db/models/lookups.py (simplified)
class HasKey(PostgresOperatorLookup):
# ...
def as_oracle(self, compiler, connection):
lhs, lhs_params = self.process_lhs(compiler, connection)
rhs, rhs_params = self.process_rhs(compiler, connection)
# PATCHED: lhs is now safely quoted
return "JSON_EXISTS(%s, '$.%s')" % (lhs, rhs), lhs_params + rhs_params
The actual patch involves changes to the as_oracle method to use connection.ops.quote_name or similar safe quoting functions.
Exploitation & Lab Setup
Red Team
Prerequisites:
- A Django application using Oracle database.
- An endpoint that uses the
HasKeylookup with user-controlledlhs(e.g., a search or filter parameter).
Exploitation Steps:
Identify an endpoint that uses
HasKeywith user input. For example:# views.py def search(request): key = request.GET.get('key') results = MyModel.objects.filter(json_field__has_key=key) return render(request, 'results.html', {'results': results})Craft a malicious
lhsvalue to inject SQL. For Oracle, the injection point is within aJSON_EXISTScall. Example payload:key=foo')) OR 1=1 --The resulting SQL might look like:
SELECT ... FROM myapp_mymodel WHERE JSON_EXISTS(json_field, '$.foo')) OR 1=1 --')Use UNION-based injection to extract data:
key=foo')) UNION SELECT username, password FROM auth_user --
Lab Setup:
- Use Docker to set up a vulnerable Django environment with Oracle XE.
- Create a simple model with a JSONField.
- Expose an endpoint that uses
HasKeywith user input.
Blue Team
Detection:
- Monitor database logs for unusual SQL queries containing
JSON_EXISTSwith unexpected parentheses or OR/UNION clauses. - Look for HTTP requests with suspicious
keyparameters containing SQL metacharacters (e.g.,',--,UNION).
Hunting:
- Search for Django applications using Oracle and the
HasKeylookup. - Review code for direct usage of
has_keywith user input.
Mitigation:
- Apply the patch immediately.
- Use a Web Application Firewall (WAF) to block SQL injection patterns.
- Implement input validation and parameterized queries.
Indicators of Compromise (IOCs)
Network:
- HTTP requests with
keyparameter containing SQL injection patterns (e.g.,' OR 1=1--,UNION SELECT). - Database queries containing
JSON_EXISTSwith unusual syntax.
- HTTP requests with
Logs:
- Django error logs showing
DatabaseErrororIntegrityErrorrelated to JSON queries. - Oracle audit logs showing
JSON_EXISTScalls with unexpected arguments.
- Django error logs showing
File System:
- Modified Django source files (if attacker has write access).
- Suspicious files in the application directory.
Detection Engineering
YARA Rule
rule CVE_2024_53908_Django_HasKey_Oracle_SQLi {
meta:
description = "Detects potential SQL injection attempts targeting Django HasKey on Oracle"
author = "Valters IT"
date = "2024-12-10"
reference = "CVE-2024-53908"
severity = "critical"
strings:
$sqli1 = /JSON_EXISTS\s*\([^)]*\)\s*OR\s*\d+=\d+/i
$sqli2 = /JSON_EXISTS\s*\([^)]*\)\s*UNION\s+SELECT/i
$sqli3 = /JSON_EXISTS\s*\([^)]*\)\s*--/i
$sqli4 = /has_key\s*=\s*['\"][^'\"]*['\"]\s*\)\s*OR/i
condition:
any of them
}
Sigma Rule
title: CVE-2024-53908 Django HasKey SQL Injection Attempt
id: 7a8b9c0d-1e2f-3a4b-5c6d-7e8f9a0b1c2d
status: experimental
description: Detects SQL injection attempts against Django's HasKey lookup on Oracle
author: Valters IT
date: 2024-12-10
references:
- https://nvd.nist.gov/vuln/detail/CVE-2024-53908
logsource:
category: webserver
product: django
detection:
selection:
c-uri|contains:
- 'has_key='
- 'key='
c-uri|re: '.*(OR|UNION|--).*'
condition: selection
falsepositives:
- Legitimate use of the word "OR" in a key name (unlikely)
level: critical
Suricata Rule
alert http any any -> any any (msg:"CVE-2024-53908 Django HasKey SQL Injection Attempt"; flow:to_server,established; content:"has_key="; nocase; pcre:"/(OR|UNION|--)/i"; classtype:web-application-attack; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Upgrade Django to version 4.2.17, 5.0.10, or 5.1.4 (or later).
- If immediate upgrade is not possible, disable the
HasKeylookup for Oracle databases by overriding theas_oraclemethod in a custom lookup class. - Review all code that uses
HasKeywith user input and ensure input is validated.
Long-term Measures:
- Implement parameterized queries for all database operations.
- Use a Web Application Firewall (WAF) to filter SQL injection attempts.
- Conduct regular security audits and penetration testing.
- Monitor for new CVEs and apply patches promptly.
Workaround:
- Avoid using
HasKeydirectly with user input. Use the__syntax instead, which is not vulnerable.
Valters IT
Securing Digital Frontiers