Using Digial Ocean, Hugo, and a LAMP stack to host a Capture the Flag Challenge


Stranger Servers is the first CTF Challenge I’ve created. The basic web challenge consists of a 90’s themed website with a hidden vulnerable php application. The inspiration for the backend comes from an older php application called timeclock which has several reported vulnerabilities (See Employee TimeClock Software 0.99 - SQL Injection)

The main challenge website is hosted on an apache webserver on a basic tier droplet from digital ocean. This is not the cheapest way to host a challenge, however, I chose this design because I was already using the server as a testing ground for vulnerability research into the timeclock application.


Seting up


Spinning up a Digital Ocean Droplet

1) First, I created a digital ocean account

2) Next, I created an ubunto droplet with a basic plan. I chose the lowest possible tier, which, for $5 a month gets you 1 GB / 1 CPU, 25 GB SSD disk, 1000 GB transfer. This will be much more then I need for the challenge, and will allow me to host other challenges on the same droplet,

3) I selected a data center region to host the droplet, and finally created SSH credentials to enable remote log in

Ubunto Server Configuration

After the server booted up, I logged into it with SSH and started some initial configuration

1) First, I ran the usual update commands to ensure I was using the latest packages

apt-get update && apt-get upgrade

2) I install Hugo, a static web generator to quickly create websites from templates. I used snap for installation

snap install hugo --channel=extended


Configuring Vulnerable Timeclock App

Now for the fun stuff.

The idea for this CTF was to use the timeclock application as a basic SQLinjectible form. Timeclock is a basic php app which enables employers to track empolyee working time through an apache, php, and mysql website. Older versions of the app are vulnerable to a host of exploits, including three on the exploit-db database. These include exploits like as Employee TimeClock Software 0.99 - SQL Injection, TimeClock Software 0.995 - Multiple SQL Injections, and TimeClock 0.99 - Cross-Site Request Forgery (Add Admin).

Each of these exploits were for older versions of timeclock. Since I was unable to find these particular versions, I settled on removing the security patches from the latest version 1.01.

I downloaded the latest version from the vendor portal at I unzipped the download package and using SCP I transfered the entire application to my digital ocean server.

scp /path/to/timeclock user@[ip address of server]:/path/to/destination

Creating a MySQL Database

Timeclock uses a mysql database to store user information such as username and passwords as well as time entry and pay rate. The app download includes a .sql file to automatically create the database. I used the following commands to set it up.

Log in and create empty database

mysql -u root -p    

mysql> CREATE DATABASE timeclock;

Log out, and modify database with .sql file

mysql -u root -p timeclock > timeclock.sql

Connecting MySQL to Timeclock App

The only setup step required for the timeclock app is to change the default configuration in the db.php file to use the correct mysql options.

// You need to change these to your settings.

/** the name of the database */
$db_name = "xxx";

/** mysql database username */
$db_user = "xxx";

/** mysql database password */
$db_password = "xxx";

/** mysql hostname */
$db_host = "xxx";

To test if the application works, I moved it to the /var/www/html directory and started the apache webserver.

cp /timeclock /var/www/html
service apache2 start 

Flag Layout

The plan for the CTF was to have 3 flags at varying levels of difficulty. Each flag would provide hints to the next, with the first flag being found through common directory scanning or a hint in the challenge description. The flags are structured like this.

  1. Beginner Flag: Located at robots.txt
  2. Intermediate Flag: Available through a simple SQL injection in the login-in field of the hidden timeclock application
  3. Intermediate-Advanced Flag: Available through either a time-based SQLinjection in the add_time form, or alternatively available through a modified SQLinjection of the second flag in the log-in field.

Making the App Vulnerable

According to some basic research, the timeclock 1.01 application is not vulnerable to any known exploits, however, older versions are. Looking at the exploit-db records for timeclock, I noticed there was a SQLinjection on the log-in form in version .99. It appears as if there was not any proper sanitization of user input in this field, leading to this exploit.

While I could not be certain, taking a look at the source code 1.01, it appears the developers added the cclean and dclean functions to sanitize inputs.

function dclean($data) {
	if ( !is_numeric ($data) ) {
		echo "Invalid Data";
	$data = htmlspecialchars($data, ENT_QUOTES);
return $data;

function cclean($data) {
	$data = htmlspecialchars($data, ENT_QUOTES);
return $data;

Removing the references to these functions, would remove any user input sanitization. The SQLi on the log-in form still would not work until I removed the password_verify function in the login_action.php file.

Original Timeclock Application

if (password_verify($timeapp_password, $password)) {
	//echo "<p>Success!</p>";
	$_SESSION['timeapp_id'] 		= $row["user_id"];
	$_SESSION['timeapp_level']		= $row["level"];
	$_SESSION["timeapp_username"]	= $row["username"];
	header ("Location: index.php?success");
}else {
	//echo "<p>Failure</p>";
	$_SESSION = array();
	header ("Location: login.php?error2");

With the p

New CTF Application

if ($result->num_rows > 0) {
   	$_SESSION['timeapp_id']                 = $row["user_id"];
        $_SESSION['timeapp_level']              = $row["level"];
        $_SESSION["timeapp_username"]   = $row["username"];
        header ("Location: index.php?timeapp_password:$timeapp_password:passcode:$passcode");
    } else {
      $_SESSION = array();
      header ("Location: login.php?better_luck_next_time:$sql");

With the password_verify function gone, any SQLi that returns a valid user can log into the app as that user.


Website Generation

To quickly create a fun front-end for the challenge. I searched through the hugo themes until I found a retro 90s theme from cshoredaniel called new-oldnew-mashup.

I mostly followed a fantastic article from Justin Ellingwood on the digital ocean website, “How To Install and Use Hugo, a Static Site Generator, on Ubuntu 14.04” for setup instructions, generating the site with the following.

hugo new site ~/Hawkins-Library
cd ~/Hawkins-Library

I edited the config file to the followig

baseurl = "http://public.ip.address"
languageCode = "en-us"
title = "Hawkins Public Library"
theme = "new-oldnew-mashup"

Last, I created new pages for the site, including the books, news, study groups, and home pages.

hugo new

When I was finished designing the front end for the challenge. I copied the generated static site into the apache web directory, restarted apache, and the challenge was live.


Overall it was a good learning experience to design, create, and host my own capture the flag challenge. In the future, I will plan on dockerizing this challenge for easier portabiliy and allow others to host the challenge locally instead of on a remote server.