Wiz CTF #2: Contain Me If You Can

Wiz CTF stamp 2

No flags are included in this writeup.

Overview

Contain Me If You Can was the first major difficulty jump for me in the championship. The challenge started inside a container and asked for a flag on the host filesystem. That sounds like a classic “escape the container” prompt, but the path was layered enough that blind exploit hunting was a waste of time.

Field Value
Month July 2025
Points 20
Main area Containers, Linux enumeration, PostgreSQL, privilege escalation

Container Recon

The first pass was standard container triage:

  • mounted filesystems
  • capabilities
  • process list and namespaces
  • network interfaces
  • environment variables
  • reachable internal services

Nothing screamed “one command escape.” That was the main signal. If the container is not privileged and the obvious mounts are absent, the next question is what this container can talk to.

The network view became more useful than the filesystem view. The challenge had another service reachable from the container, and the interesting path moved from local escape to lateral movement.

The Useful Pivot

The important discovery was database access. Once PostgreSQL entered the picture, I stopped thinking only in terms of container boundaries and started asking what execution context the database had.

The flow was:

  1. discover the internal database service
  2. obtain or infer usable database access
  3. inspect database permissions
  4. use PostgreSQL functionality to execute a command in the database service context

PostgreSQL command execution is always environment-dependent. In this challenge, the database process became the bridge from “I am stuck in a container” to “I can influence another process with different local privileges.”

Privilege Escalation

After gaining command execution through the database path, the next step was local privilege review. The important misconfiguration was a sudo rule that allowed a sensitive action without a password.

That turned the solve into a chain:

  • container shell gives initial position
  • network enumeration finds database
  • database execution gives a stronger local foothold
  • sudo configuration gives privilege escalation
  • host filesystem access becomes possible

The final host access was about identifying the right host device/path and mounting or reading it from the elevated context. The challenge was not about brute force. It was about patiently moving through contexts and checking what each context could do.

Root Cause

The core security issue was trust leaking across layers:

  • the container had enough network reach to access a privileged internal service
  • the database environment exposed command execution opportunities
  • local sudo rules were too permissive
  • host storage was reachable after privilege escalation

Each individual step may look survivable in isolation. Together they become a container escape.

Takeaways

The biggest lesson from this challenge was that container escape is often not a kernel exploit story. It can be an application and operations story.

Things I would audit in real infrastructure:

  • whether app containers can reach internal databases unnecessarily
  • whether database roles can use server-side file or command execution features
  • whether service users have passwordless sudo paths
  • whether host block devices or host paths are visible after lateral movement
  • whether logs connect database execution events to container-originated traffic

Contain Me If You Can felt much harder than the first stamp because the solve required changing mental models mid-way. The container was only the starting room, not the whole challenge.