Have you ever run a CTF event and used CTFd to support your competition? If you did, you might have faced the challenge to import your existing CTF challenges into the platform or losing the database after an incompatible upgrade.
I was looking for an option to import and export challenges in a portable, human-readable format (YAML).
This is how I come across https://github.com/tamuctf/ctfd-portable-challenges-plugin. I have updated the plugin to be compatible with the latest version of CTFd and I plan to maintain it if there is interest.
My challenges have the following folder structure:
$ ls
0x01 Challange Name 1
ctfd.yml
attachements/attachement.txt
0x02 Challange Name 2
ctfd.yml
attachements/attachement.txt
I wrote a script that will parse automatically all these folders, merges the ctfd.yml files and create a zip with the merged YAML files and the attachments. This file can then be imported by the plugin. If you do not want to automate this process, you can create this archive manually too.
The CTFd plugin has the following objectives:
- Allow challenges to be saved outside of the database
- Allow for source control on challenges
- Allow for easy human editing of challenges offline
- Enable rapid deployment of challenges to a CTFd instance
The importer.py and exporter.py scripts can be called directly from the CLI. This is much preferred if the archive you are uploading/downloading is saved on the server because it will not need to use the network.
Give it a try and send me your feedback or ideas for improvements.
Example YAML File
--- category: tristique description: Aenean nulla dolor, imperdiet id massa eu, iaculis mattis urna. Nullam commodo velit nec tellus egestas, quis varius nulla malesuada. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Morbi dapibus lorem non tristique placerat. Lorem ipsum dolor sit amet, consectetur adipiscing elit. files: - export.d/8f227f1c7f305b3fcd39cc06d54a7e36/bfn1o8t5s6dy.gif - export.d/4ab77d38dd646bb81e8d6d2533eec71c/bPXFXW7.mp4 flags: - flag: pharetra name: Duis value: 10 hints: - hint: 'Hint: Buda huba cupa? nulla musca' type: standard cost: 2 --- category: netus description: Duis nibh elit, ultricies non erat non, vulputate vestibulum risus. Nullam posuere ac nisi vitae lobortis. Vivamus convallis dictum nunc sed cursus. files: - export.d/1e9f731e310179959337a26307356513/LYVIZ4x.mp4 flags: - flag: ante hidden: true name: Integer value: 30 type: dynamic initial: 300 decay: 10 minimum: 1