From SSTI to Host Root: Compromising a Dockerized Environment in PwnUP CTF 2
How a Server-Side Template Injection vulnerability led to full host compromise through a privileged Docker container.
From SSTI to Host Root: Compromising a Dockerized Environment in PwnUP CTF 2
How a Server-Side Template Injection vulnerability led to full host compromise through a privileged Docker container.

Introduction
During the CyberForce PwnUP internship program, I analyzed and exploited a vulnerable web application environment designed for security training purposes.
The target machine exposed multiple web services and containerized applications. What initially appeared to be a simple web vulnerability eventually resulted in complete control of the underlying host operating system.
This article walks through the attack chain, the vulnerabilities involved, and the lessons learned from the assessment.
Disclaimer: All activities described in this article were performed in an authorized CTF/laboratory environment created for educational purposes.
Target Overview
The target system was hosted at:
192.168.1.104
The objective was to identify vulnerabilities, gain access to the system, escalate privileges, and retrieve all challenge flags.
Tools Used
- Nmap
- Burp Suite
- Netcat
- SQLite3
- Linux Utilities (mount, chroot, passwd)
Reconnaissance
The first step was identifying exposed services.
nmap -sC -sV -p- 192.168.1.104
The scan revealed the following services:
PortService22OpenSSH 9.6p18081Python/Werkzeug Web Application8082Python/Werkzeug Web Application
The most interesting target appeared to be the web application running on port 8081.


Discovering an SSTI Vulnerability
While interacting with the application’s search functionality, I noticed that user-supplied input was being processed directly by the template engine.
Testing with a simple payload:
{{7*7}}
returned:
49

This confirmed the presence of a Server-Side Template Injection (SSTI) vulnerability.
At this point, arbitrary template expressions were being executed on the server.
Achieving Remote Code Execution
After confirming SSTI, the next goal was determining whether it could be escalated into Remote Code Execution (RCE).
Using the exposed Jinja2 environment, it was possible to access Python internals and execute operating system commands.
A reverse shell payload was delivered through the vulnerable parameter, resulting in a connection back to the attacking machine.
Once the reverse shell connected successfully, interactive command execution on the target became possible.
The initial shell was obtained with root privileges inside the container.
This was already significant, but the ultimate objective was gaining control of the host operating system itself.

Investigating the Container Environment
With shell access established, I began examining the Docker environment.
Several indicators suggested that the container was running in an unsafe configuration.
Inspection of mounted devices revealed direct access to host resources.
Further investigation showed that the container had been launched with the Docker:
--privileged
flag.

This configuration effectively removes most container isolation protections and grants extensive access to the host system.

Escaping the Container
Because the host’s disk device was exposed inside the container, it could be mounted directly.
After mounting the host filesystem, it became possible to interact with the host operating system from within the container.
Using a chroot operation, the environment was switched from the container filesystem to the host filesystem.
At this point, the attack moved beyond the container boundary and into the host operating system itself.
The isolation model had completely failed.

Obtaining Host Root Access
Once operating inside the host filesystem, full administrative control was available.
Verification of host compromise was performed by modifying the host root account credentials.
This demonstrated that the host operating system had been completely compromised and that persistent administrative access could be established.
The attack chain had now progressed from:
Web Application
↓
SSTI
↓
Remote Code Execution
↓
Container Root
↓
Container Escape
↓
Host Root
Lateral Movement
After compromising the host, I investigated the second application running on port 8082.
Source code analysis revealed insecure usage of:
pickle.loads()
The application deserialized untrusted data using Python’s Pickle mechanism.
This vulnerability can lead to arbitrary code execution and is a well-known security risk.
During further investigation, Docker layers and backup archives stored on the system were analyzed, revealing additional sensitive information.
Sensitive Information Discovered
Several pieces of information were recovered during the assessment:
Application Credentials
Database analysis revealed credentials stored within the application:
admin:admin123
user:user123
Challenge Flags
All challenge flags hidden across containers, application directories, and Docker layers were successfully recovered.
Root Cause Analysis
The compromise was possible because multiple critical weaknesses existed simultaneously.
1. Server-Side Template Injection
User input was rendered directly inside a Jinja2 template engine without proper sanitization.
Impact:
- Remote Code Execution
- Server compromise
- Full application takeover
2. Privileged Docker Container
The container was launched using:
--privilege
Impact:
- Access to host devices
- Container isolation bypass
- Host compromise
3. Insecure Deserialization
The application relied on:
pickle.loads()
for deserializing untrusted data.
Impact:
- Arbitrary code execution
- Lateral movement opportunities
- Data exposure
Remediation Recommendations
Avoid Privileged Containers
Containers should never be executed with:
--privileged
unless absolutely necessary.
Instead, grant only the minimum required capabilities.
Secure Template Rendering
Never pass user-controlled data directly into template engines.
Use safe rendering mechanisms and strict input validation.
Eliminate Pickle for Untrusted Data
Avoid using Pickle when handling external input.
Safer alternatives include:
- JSON
- YAML (with safe loaders)
- Protocol Buffers
Conclusion
This challenge demonstrates how seemingly independent security issues can combine into a complete system compromise.
A simple SSTI vulnerability was enough to obtain code execution, but the real impact came from an insecure Docker configuration that allowed a transition from container access to full host control.
The exercise highlights an important security lesson:
Containers are not security boundaries when they are configured incorrectly.
A single web vulnerability should never be capable of becoming host-level compromise. Proper container isolation, secure coding practices, and principle-of-least-privilege configurations are essential for preventing these attack chains from succeeding.


Author: Mert İçdem Topic: Web Application Security, Docker Security, Privilege Escalation, Container Escape, Penetration Testing, CTF Writeups
메타데이터
- post_id
- aef4e5e13d3f
- slug
- from-ssti-to-host-root-compromising-a-dockerized-environment-in-pwnup-ctf-2-aef4e5e13d3f
- url
- https://medium.com/@merticdembusiness/from-ssti-to-host-root-compromising-a-dockerized-environment-in-pwnup-ctf-2-aef4e5e13d3f
- canonical_url
- https://medium.com/@merticdembusiness/from-ssti-to-host-root-compromising-a-dockerized-environment-in-pwnup-ctf-2-aef4e5e13d3f
- author_url
- https://medium.com/@merticdembusiness
- status
- ok
- fetched_at
- 2026-08-30 14:23:32