# SQL Injection Django lewat FilteredRelation: CVE-2025-13372

> Kerentanan injeksi Django SQL kritis melalui perluasan kamus FilteredRelation pada basis data PostgreSQL.

**URL:** https://www.ciptadusa.com/blog/django-sql-injection-filteredrelation-cve-2025-13372  
**Type:** blog  
**Author:** PT Cipta Dua Saudara  
**Category:** Keamanan Aplikasi  
**Published:** 2026-05-30  
**Cover:** https://www.ciptadusa.com/media/defaults/blog-cover.svg  

## Article

# Injeksi Django SQL melalui FilteredRelation: CVE-2025-13372

## Ringkasan

Kerentanan injeksi SQL kritis ditemukan di sistem ORM Django, khususnya di fitur `FilteredRelation`. Dilacak sebagai CVE-2025-13372, kerentanan ini mempengaruhi Django versi 5.2 sebelum 5.2.9, 5.1 sebelum 5.1.15, dan 4.2 sebelum 4.2.27.

## Detail teknis

### Deskripsi Kerentanan

Kerentanan ada dalam cara `FilteredRelation` Django menangani alias kolom ketika menggunakan perluasan kamus (`**kwargs`) dengan metode `QuerySet.annotate()` atau `QuerySet.alias()` pada basis data PostgreSQL.

### Root cause

Ketika developer menggunakan perluasan kamus dengan `QuerySet.annotate()` atau `QuerySet.alias()`, Django gagal membersihkan nama alias kolom dengan benar. Hal ini memungkinkan penyerang untuk memasukkan kode SQL arbitrer melalui kunci kamus yang crafted.

### Pola Kode yang Terkena Dampak

```python
# Vulnerable pattern
from django.db.models import FilteredRelation, Q

# Using dictionary expansion with user-controlled data
user_input = request.GET.get('filter_name', 'default')
kwargs = {user_input: FilteredRelation('relation', condition=Q(...))}

# This is vulnerable
queryset = queryset.annotate(**kwargs)
```

### Contoh Eksploitasi

Seorang penyerang dapat memasukkan SQL melalui kunci kamus:

```python
# Malicious input
user_input = "malicious_alias'; DROP TABLE users; --"

# Results in SQL injection
kwargs = {user_input: FilteredRelation('relation')}
queryset = queryset.annotate(**kwargs)
```

## Dampak

### Tingkat Keparahan: Kritis

- **Kerahasiaan**: Tinggi - Akses ke semua data database
- **Integritas**: Tinggi - Modifikasi atau penghapusan data
- **Ketersediaan**: Tinggi - Potensi kehancuran basis data

### Basis Data yang Terkena Dampak

- PostgreSQL (target utama)
- MySQL dan MariaDB (CVE-2025-59681 mengatasi masalah serupa)

## Mitigasi

### Langkah cepat

1. **Perbarui Django** ke versi yang ditambal:
   - Django 5.2.9 atau lebih baru
   - Django 5.1.15 atau lebih baru
   - Django 4.2.27 atau lebih baru

2. **Audit Codebase**: Mencari pola yang rentan:
   ```bash
   grep -r "annotate(\*\*" --include="*.py"
   grep -r "alias(\*\*" --include="*.py"
   ```

### Remediasi Kode

```python
# Before (vulnerable)
kwargs = {user_input: FilteredRelation('relation')}
queryset = queryset.annotate(**kwargs)

# After (safe)
# Option 1: Use explicit keyword arguments
queryset = queryset.annotate(
    safe_name=FilteredRelation('relation')
)

# Option 2: Validate input against allowlist
ALLOWED_FILTERS = ['category', 'status', 'type']
if user_input in ALLOWED_FILTERS:
    queryset = queryset.annotate(**{user_input: FilteredRelation('relation')})
```

### Pertahanan Secara Mendalam

```python
# Use Django's built-in protection mechanisms
from django.db.models import FilteredRelation, Q

def safe_annotate_with_filtered_relation(queryset, filter_name, relation, condition):
    """Safely apply FilteredRelation with input validation."""
    # Validate filter name
    if not filter_name.isidentifier():
        raise ValueError("Invalid filter name")
    
    # Use explicit keyword argument
    return queryset.annotate(
        **{filter_name: FilteredRelation(relation, condition=condition)}
    )
```

## Kerentanan Terkait

### CVE-2025-59681

Kerentanan injeksi SQL serupa memengaruhi MySQL dan MariaDB melalui metode `QuerySet.annotate()`, `QuerySet.alias()`, `QuerySet.aggregate()`, dan `QuerySet.extra()`.

### CVE-2024-39329

Kerentanan enumerasi pengguna melalui serangan waktu pada backend autentikasi.

## Praktik Terbaik untuk Keamanan Django ORM

### Validasi Masukan

1. **Jangan pernah mempercayai masukan pengguna**: Selalu validasi dan sanitasi
2. **Gunakan daftar yang diizinkan**: Tentukan nilai yang dapat diterima untuk parameter dinamis
3. **Hindari interpolasi string**: Gunakan kueri berparameter

### Penggunaan ORM

```python
# Safe patterns
# 1. Use explicit keyword arguments
queryset = queryset.annotate(count=Count('items'))

# 2. Use Q objects for dynamic conditions
from django.db.models import Q
condition = Q(status='active') & Q(created_at__year=2024)
queryset = queryset.filter(condition)

# 3. Use Django's built-in methods
queryset = queryset.values('category').annotate(total=Count('id'))
```

### Pengujian Keamanan

```python
# Test for SQL injection
import pytest
from django.test import RequestFactory

def test_filtered_relation_injection():
    """Test that SQL injection attempts are blocked."""
    malicious_input = "test'; DROP TABLE users; --"
    
    with pytest.raises(ValueError):
        # Should raise error for invalid input
        safe_annotate_with_filtered_relation(
            MyModel.objects.all(),
            malicious_input,
            'relation',
            Q(status='active')
        )
```

## Pembaruan Keamanan Django

Tim keamanan Django mempunyai rekam jejak yang kuat dalam mengatasi kerentanan dengan segera. Pembaruan keamanan rutin dirilis melalui:

- Milis keamanan Django
- Advisory keamanan GitHub
- Halaman keamanan dokumentasi Django

## Penutup

CVE-2025-13372 menggarisbawahi pentingnya validasi input bahkan ketika menggunakan sistem ORM. Meskipun ORM menyediakan lapisan abstraksi yang dapat mencegah banyak serangan injeksi SQL, developer tetap harus berhati-hati dengan konstruksi kueri dinamis.

## Referensi

- [NVD - CVE-2025-13372](https://nvd.nist.gov/vuln/detail/CVE-2025-13372)
- [Rilis Keamanan Django](https://docs.djangoproject.com/en/dev/releases/security/)
- [Dokumentasi Django - FilteredRelation](https://docs.djangoproject.com/en/stable/ref/models/expressions/#filteredrelation)

---

*Markdown version of https://www.ciptadusa.com/blog/django-sql-injection-filteredrelation-cve-2025-13372 — generated for AI agents and LLM crawlers.*
