Skip to content
A CTFd like Site, written in go
Go TypeScript HTML CSS JavaScript
Branch: master
Clone or download
nzbr Merge pull request #58 from noraj/patch-1
add rawsec inventory badge
Latest commit 4c76900 Jan 6, 2020
Type Name Latest commit message Commit time
Failed to load latest commit information.
.github Revert "added reviewdog for testing" Nov 4, 2019
cmd redid all the go imports Oct 25, 2019
frontend-dev fixed package.json packages Nov 4, 2019
html put db into it's own module Nov 4, 2019
internal fixed tests Nov 4, 2019
.gitlab-ci.yml changed ci to support packr2 Oct 11, 2019
LICENSE Switch license to AGPLv3 Sep 25, 2019 add rawsec inventory badge Dec 12, 2019
api.yml api.yml - verify summary Oct 30, 2019
demo.png a Oct 25, 2019
go.mod Update go dependencies Nov 12, 2019
go.sum Update go dependencies Nov 12, 2019
icon.svg fixed page size Nov 8, 2019
package-lock.json made webpack work Oct 31, 2019
wtfd.service Add systemd unit file Sep 30, 2019


License Latest stable version
Build Status Codecov Dependencies Repository Size
Last Commit Contributors Open Issues Open PRs Rawsec's CyberSecurity Inventory

a CTFd-like Server in go



You need a config.json in the same path as your wtfd binary (or the path you're in if you do go run ./cmd/wtfd.go)

It shall look like that:

        "Port": <The Port WTFd should run (ports <1024 need root (don't run WTFd as root))>,
        "challinfodir": "<The (relative or absolute) directory with your challenge infos>",
        "social": "<Html for the down left corner (e.g. \u003ca class=\"link sociallink\" href=\"\"\u003e\u003cspan class=\"mdi mdi-github-circle\"\u003e\u003c/span\u003e GitHub\u003c/a\u003e)>",
        "icon": "<top left icon (e.g. icon.svg)>",
        "firstline": "<first line in the top left>",
	"secondline": "<second line in the top left>",
       	"sshhost": "<The domain of your ssh challenges>"
	"servicedeskaddress": <Mail address for a GitLab service desk instance (or '-' if it is disabled),
	"smtprelaymailwithport": "<Sender address (e.g.>",
	"smtprelaymailpassword": "<Password for sender>",
	"ServiceDeskRateLimitInterval": <Interval (in seconds) where access is tracked>,
	"ServiceDeskRateLimitReports": <Maximun ammount of access per user in interval> 
	"restrict_email_domains": <array of domains>
	"require_email_verification": <bool>
	"email_verification_token_lifetime": <duration string (in "ns", "us" (or "µs"), "ms", "s", "m", "h")>

WTFd will also generate the field Key in which the cookie session key will be stored

The Challenge info Dir shall look like that:

├── chall-1
│   ├── meta.json
│   ├──
│   └──
├── chall-2
│   ├── meta.json
│   ├──
│   └──

For each Challenge you need a meta.json, a and a

The meta.json shall look like that:

	"points": <How many points the challenge should have>,
        "uri": "<Protocol and user of your ssh Challenges (e.g. `ssh://chall-1@%s`>",
	"deps": [<Dependencies the Challenge has>],
	"flag": "<The flag>",
	"author": "<The author of the challenge>"

The and are markdown files (syntax). The contents can only be seen by users who already solved the challenge

Building WTFd yourself

You need to have go, sqlite3 and npm installed

git clone
cd wtfd
cd frontend-dev
npm install # Install JS Dependencies
npx webpack --config # Compile the JS
cd ..
go build ./cmd/wtfd.go

Running WTFd

Now you can finally start wtfd by downloading it from the releases, giving it permissions chmod +x wtfd and running it ./wtfd

WTFd is HTTP only, if you need HTTPS use a reverse proxy like Traefik or nginx

Development notes

To make working with the TypeScript easier, you can do

npx webpack --config -w

to automatically compile the JS on changes

You can’t perform that action at this time.