pwneglyph logo
web python arbitrary-file-write code-execution sitecustomize gunicorn import-hooks

Plant code in an auto-imported module (sitecustomize.py) via a file-write primitive, then force a worker restart to execute it.

Overwriting sitecustomize.py + Forcing Worker Restart

sitecustomize.py is imported automatically at Python startup if it exists on the import path. Writing to it effectively plants code that runs on the next interpreter start. Long-running web workers hide the effect until you can force a process restart or recycle.

Why It Works

  • Implicit import hooks run with no further interaction once the interpreter restarts.
  • Worker recycling (timeouts, max-requests, idle restart) gives you a reliable trigger.

Vulnerable Pattern

  • An internal upload or file-write endpoint that can place files inside user site-packages, the app root, or another import path reachable at worker startup.
  • Gunicorn (or similar) configured with worker recycling, timeouts, or max-request rotation.

Exploit Flow

  1. Map writable paths exposed by the file-write endpoint.
  2. Prioritize implicit import hooks: sitecustomize.py, usercustomize.py, package __init__.py, app entrypoint modules, auto-loaded settings.
  3. Write minimal, reliable post-restart code (copy the flag, drop a simple artifact) — avoid timing-sensitive logic.
  4. Trigger restart by flooding requests, hitting max-requests, causing an idle timeout, or crashing the worker if safe.

Variations

  • If user site-packages aren't writable, target application-local imports executed on every worker fork.
  • If restart is hard, aim for modules imported lazily during request handling instead of startup hooks.

Common Blockers

  • Write path belongs to another user, filenames are sanitized, or the service runs with a frozen PYTHONPATH.

PoC Sketch

# upload to /home/<user>/.local/lib/python3.11/site-packages/sitecustomize.py
import os; os.system("cp /flag /tmp/flag.txt")
# then hammer the app until the worker respawns

Good Situations To Use It

  • You have arbitrary write but no immediate execution.
  • The process manager recycles workers.
  • A site-packages or app-root path is writable.

Sources

  • 0xFUN2026/web/skyport_ops