I was working on creating a CTF for students. I’m using CTFd since it’s so simple to setup and use. You can check it out here: https://github.com/CTFd/CTFd/wiki/Getting-Started
Anyways, I’ve played some CTFs and have noticed that some of them provide web shell or SSH access. For example, pwnable.kr (http://pwnable.kr) provides SSH access. PicoCTF (https://github.com/picoCTF/picoCTF ) also has a module for providing a shell. I also noticed that PentesterLab (https://pentesterlab.com) providers web shell as well. TAMUctf also has a plugin for CTFd here: https://github.com/tamuctf/ctfd-shell-plugin.
Providing shell to players can allow you to provide binaries, tools, and other files to the player easily. Also, you can have a category of challenges (example: how to use CLI or do basic things on Linux) specific to the container you provided.
Goal
My goal is to basically provide web shell to a Docker container for users. I’ll be adding users to the docker container, just like some other CTFs/plugins have.
I also want to do it from inside of CTFd. This way, the players don’t have to register on another site or do anything like that. (my first idea was to make them register on another web server…) Finally, I also want this to be simple for me.
Here’s my Github repo with the plugin I wrote and my Dockerfile: https://github.com/BoredHackerBlog/ctfdwettyshell
Setup
For my setup, I’ve decided to obviously have a docker container. I’m using ubuntu 16.04. For web shell, I’ve decided to go with wetty. You can check out wetty here: https://github.com/krishnasrinivas/wetty It’s very simple to use.
First I decided to make my docker image, which includes wetty. Here’s the Dockerfile:
The Dockerfile can obviously be modified to include more tools and custom scripts.
After the file was created, I used “docker build” to build the image (mine is called wettytest, since I was just testing). I started up the image by running “docker run” command.
Now I needed to add a plugin to CTFd. The goal of this plugin was to:
See if a user has been assigned creds or not
- If the user has been assigned creds
- Return creds
- If the user hasn’t been assigned creds
- Randomly generate username and password
- Add user to the docker container
- Return creds
More information about creating CTFd plugin is here: https://github.com/CTFd/CTFd/wiki/Plugins
I didn’t exactly follow the guidelines provided by CTFd for this. For some reason, I couldn’t get my script to add a table and store values in the database. I finally gave up and went with storing the login information in a dictionary.
Here’s what the plugin script looks like:
If the plugin is used then container_name string and return_info string obviously need to change to match your setup.
I also added a page via the Admin page on CTFd which redirects to /docker. It looks like this:
When that page is added, a link to Docker page should show up on non-admin pages like below:
Results
It works for my needs.
When the player visits the docker page, this is presented:
And the player is able to log in:
Issues
There are several issues with doing this that I haven’t had the need to fix yet.
If a user changes their password while in the container and forgets about it, they lose access to it. If their password is accidentally leaked or shared, they can’t change it.
Login info is lost if CTFd web app is restarted. Since I was having trouble with storing login info into CTFd database, I went with a dictionary and I’m not permanently storing that data and reloading it every time. When CTFd is restarted and the player visits /docker, a new user is created.
Docker container is allowed to access the internet. Depending on your setup and your users, you may or may not want that ability.
Resources
https://github.com/BoredHackerBlog/ctfdwettyshell
https://github.com/CTFd/
https://github.com/CTFd/CTFd/wiki/Plugins
https://github.com/tamuctf/ctfd-shell-plugin
https://github.com/picoCTF/picoCTF
https://pentesterlab.com
http://pwnable.kr
https://github.com/krishnasrinivas/wetty