How to Deploy a Docker Container Challenges

Modified on Sun, 17 Aug at 7:55 AM

Table of Contents 

1. Overview 

2. Docker Container Setup 

3. Dynamic Flag Implementation 

4. Flag Handling Methods 

5. Platform Integration 

6. Local Testing 

7. Example Challenge 



Overview 


Docker Container challenges offer realistic, hands-on scenarios where participants interact with a live environment to solve the challenge. These are perfect for topics like exploitation, privilege escalation, and network security.

Here’s how to create a Container challenge using the Simulations Labs platform.


Deploying containers

1. Go to the Challenges Tab

From your dashboard, navigate to the Challenges tab in the sidebar.
 Click the 
“Create New Challenge” button.


2. Select Challenge Type and Upload Docker Container File

In the creation form:

  • Select “Container” as the Challenge Type.

  • Upload the Docker container (in .zip fomat) in the Docker section

    • It should have the following structure

| Challenge.zip:
| —--- Hosting
| —--- —--- Dockerfile
| —--- —--- (all necessary files 
and folders for the challenge)




Notes:  
- Infrastructure currently doesn’t support docker compose. 
- The container should be running on port 80.



3. Fill in the Challenge Details

Provide all necessary information for the challenge:

  • Name

  • Category

  • Tags
    Select from the dropdown the relevant keywords like linuxprivescbeginner.

  • Level
    Select difficulty: Basic, Easy, Medium, Hard or Advanced.

  • Duration (Optional)
    Estimated time to solve (in minutes).

  • Points
     Set the score value.
    Example: 300

  • Solution
     Enter the expected flag or answer.
     Example: 
    flag{got_root_access}

  • Description
     Write the full scenario that the participant will encounter. Include relevant background, objectives, and hints.


Example:
You’ve gained access to a user shell on this Linux machine. Your goal is to escalate privileges and find the root flag in 
/root/flag.txt.



4. Save and Preview

Once all fields are filled:

  • Click “Save” to create the challenge.

  • Wait for 5-10 minutes and the challenge link should be added to the Images Manager tab (if not there is likely an issue with your container, review it and if the issue persists contact the help center).




You can go to the Preview tab to see how the challenge will appear to participants before assigning it to a CTF.




Docker Container Setup 


First, we setup a regular Dockerfile for the challenge container:

# Use PHP 8.4.8 with Apache on Debian Bookworm 
FROM php:8.4.8-apache-bookworm 
# Update package lists and install ping utility for the challenge RUN apt update && apt install iputils-ping -y 
# Remove default Apache web files 
RUN rm -rf /var/www/html/ 
# Copy challenge web files to Apache document root 
COPY ./html /var/www/html/ 
# Set proper ownership for web files 
RUN chown -R www-data:www-data /var/www/html/ 
# Copy initialization script that handles dynamic flags COPY init.sh /init.sh 
# Make init script executable (700 = read/write/execute for owner only) RUN chmod 700 /init.sh 
# Run initialization script when container starts 
CMD ["/init.sh"] 


Key Components Explained: 


• Base Image: PHP with Apache for web-based challenges 

• Package Installationiputils-ping for the RCE challenge functionality 

• File Structure: Web files in /var/www/html/ , init script in root 

• Security: Proper file ownership and restrictive permissions on init script 

• Entry Point: Custom init script handles dynamic flag setup before starting services 



Dynamic Flag Implementation 


The core dynamic flag logic is implemented in the init.sh script:

#!/bin/sh 
# Check if Dynamic Flag environment variable is set 
if [ -z "$DF]; then 
# If DF is not set, use hardcoded static flag 
echo 'Flag{rce_example}' /flag.txt 
else 
# If DF is set, use the dynamic flag from environment 
echo $DF /flag.txt 
fi 
# Unset the environment variable for security 
unset DF 
# Start Apache web server 
service apache2 start 
# Keep container running 
tail -f /dev/null 


Critical Steps Explained: 

1. Flag Check[ -z "$DF" ] tests if the DF environment variable is empty or unset 

2. Static Fallback: When no dynamic flag is provided, use the hardcoded flag for local testing 3. Dynamic Flag Usage: When DF is set, write it to the flag file 

4. Security Cleanupunset DF removes the flag from environment variables to prevent exposure 

5. Service Startup: Start Apache to serve the web application 

6. Container Persistencetail -f /dev/null keeps the container running 

Flag Handling Methods 

Method 1: Simple Text File Storage 


The basic approach stores the flag directly in a text file:

if [ -z "$DF]; then 
echo 'Flag{rce_example}' /flag.txt 
else 
echo $DF /flag.txt 
fi 
unset DF 

Usage: Flag is accessible via file system commands like cat /flag.txt 

Method 2: PHP Variable Integration 

For PHP-based challenges, the flag can be embedded as a PHP variable: 

if [ -z "$DF]; then 
# Static flag for local testing 
echo "<?php \$flag='Flag{flagggg}' ;?>" /var/www/html/flag.php else 
# Dynamic flag from platform 
echo "<?php \$flag='${DF}' ;?>" /var/www/html/flag.php fi 


Usage

• The flag.php file is accessible to users but don't show the flag • Other PHP files can include this file: include 'flag.php'; 

• Flag is accessed via the $flag variable in PHP code 


Method 3: Application Memory Storage 

For more complex scenarios:

# Store flag temporarily 
if [ -z "$DF]; then 
echo 'Flag{static_flag}' /tmp/flag.txt 
else 
echo $DF /tmp/flag.txt 
fi 
unset DF 
# Application reads flag into memory then deletes file 
# (This would be handled by the application code) 


Key Principle: The handling of dynamic flags differs based on the challenge requirements, but the main workflow is always: 

1. Check if dynamic flag is provided 

2. Store/process the flag appropriately 

3. Unset the environment variable for security 



Platform Integration 


Challenge Creation Options 

When creating a challenge on the platform, you have two options: 


Option 1: Normal (Static) Flag Mode 

• Purpose: Traditional CTF mode where all users get the same flag 

• Requirement: The hardcoded flag in init.sh must match exactly the flag set in the solution 

• Platform Behavior: Simply compares user submission with the static flag 

• Use Case: Quick challenges or when flag uniqueness is not required 


Option 2: Dynamic Flag Mode 

• Purpose: Each user gets a unique flag to prevent sharing 

• Process: Platform backend generates unique flags using the base flag from solution plus

additional parameters 

• Container Deployment: Platform passes the unique flag via DF environment variable • Kubernetes Integration: Platform uses Kubernetes to deploy containers with environment variables 

• Security: Each user's container is isolated with their specific flag 


Platform Backend Process 


When Dynamic mode is selected: 

1. Platform takes the flag from the solution configuration 

2. Combines it with other parameters 

3. Generates a unique dynamic flag for that user 

4. Deploys container via Kubernetes with the DF environment variable 

5. User solves the challenge and receives their unique flag 

6. Platform validates the submitted flag against the generated dynamic flag 




Local Testing 

For local development and testing, use the provided build.sh script: 

#!/bin/bash 
# Clean up any existing container 
docker rm -f dynamic_flag_example 
# Build the Docker image 
docker build -t dynamic_flag_example && 
# Option 1: Run with static flag 
# docker run --name=dynamic_flag_example --rm -p80:80 -it dynamic_flag_example 
# Option 2: Run with dynamic flag 
docker run --name=dynamic_flag_example --rm -p80:80 -e DF="Flag{ThisIsDynamicFlag}" -it d

Testing Options:

• Static Mode: Uncomment the first docker run command to test with hardcoded flag 

• Dynamic Mode: Use the second command to simulate platform behavior with custom flag 

• Port Mapping-p80:80 maps container port 80 to host port 80 

• Environment Variable-e DF="Flag{...}" simulates the platform passing the dynamic flag 


Notes: This Docker command is for local testing only. The actual platform uses Kubernetes orchestration for container deployment and management.



Example Challenge 


The provided example demonstrates a Remote Code Execution (RCE) vulnerability in a PHP web application. 


Challenge Files Structure: 

Example/ 

├── Dockerfile # Container configuration 

├── init.sh # Dynamic flag handler 

├── build.sh # Local testing script 

└── html/ 

└── index.php # Vulnerable web application



Vulnerable Application ( index.php ): 

<?php 
// Network monitoring tool with RCE vulnerability 
$result ''
if (isset($_GET['host'])) { 
$host $_GET['host']; 
// VULNERABILITY: No input validation - direct shell execution $result shell_exec("ping -c 1 $host"); 

?> 
<!DOCTYPE html> 
<html
<head
<title>Network Monitor</title
</head
<body
<h1>Ping a Host</h1
<form method="GET"> 
<input type="textname="hostplaceholder="Enter hostname or IP"> <button type="submit">Ping</button
</form
<h3>Result:</h3
<pre><?php echo $result ?></pre
</body
</html> 



Solution 

The challenge can be solved by exploiting the RCE vulnerability: 


Payloadgoogle.com > /dev/null && cat /flag.txt 


Explanation

• google.com > /dev/null: Executes ping command and discards output 

• &&: Logical AND operator - executes next command if first succeeds 

• cat /flag.txt: Reads the flag file containing the dynamic flag


URL Example

http://localhost/?host=google.com%20%3E%20/dev/null%20%26%26%20cat%20/flag.txt 

This payload demonstrates how the dynamic flag system works - regardless of whether the flag is static or dynamic, the solution method remains the same, but each user receives their unique flag value. 


Important Notes: 

• The focus of this documentation is on dynamic flag implementation, not vulnerability analysis 

• The example solution is provided for testing purposes 

• In production, the platform handles container orchestration through Kubernetes 

• Always ensure the static flag in init.sh matches the solution flag when using Normal mode 

• When using the dynamic flag ensure that the static flag is short and don't contain irregular characters example Flag{dynamic_flag}



Attachments (1)

Was this article helpful?

That’s Great!

Thank you for your feedback

Sorry! We couldn't be helpful

Thank you for your feedback

Let us know how can we improve this article!

Select at least one of the reasons
CAPTCHA verification is required.

Feedback sent

We appreciate your effort and will try to fix the article