Last year, Red Hat Product Security organization celebrated its 20th birthday, for that occasion, my team created a CTF for Red Hat employees. It turned out to be a pretty nice event with players showing interest in participating again, so we did a new edition. This year’s CTF was hosted during the “We Are Red Hat Week” with infrastructure/challenges created by Janos Bonic, Oleg Sushchenko, and myself with help from other parts of the company for the non-technical aspects of it all.
Besides the obvious argument of the CTF being a nice platform to encourage engineer’s security awareness through gamification, creating challenges and dealing with the infrastructure turned out to be pretty interesting. I took the opportunity of having little constraints to deviate from typical CTF challenges a bit and dabble in tech/techniques I needed some excuse to play with: Double SQL prepare injections, eBPF tc filter, WebAssembly, &cie. <ramblings> We had a pretty technically diverse audience for this CTF, most of whom had never participated in such an event before, and some were at loss with how to proceed. Challenges should perhaps be accompanied by a more educational track, so all levels can benefit and have fun. </ramblings>
Some players made writeups for most of the challenges and/or showcased their solutions in the closing event, thanks to them! If you’re curious of some of the challenges, here is a list of public writeups:
The infrastructure running the challenges was pretty different from last year’s infrastructure (Kubernetes + external HaProxy) and hinges purely on k3s. In retrospect this is the obvious choice: k3s is light to run and has all we needed, Traefik for ingress controller and Klipper for a service load balancer (we had 3 nodes running).
The goodness of having Traefik bundled-in is made a bit annoying by the slightly different configurations for versions as reflected by the mess of StackOverflow responses and Traefik reference docs’ organization. So here’s a recap of the info I needed for all things Traefik on k3s version v1.24.4:
Define and expose an UDP entrypoint + redirect web entrypoint to websecure. Edit helm’s manifest for Traefik’s configuration on the master node /var/lib/rancher/k3s/server/manifests/traefik-config.yaml, here the entrypoint is called udpep:
Define a custom TLS certificate to be used for all Traefik https endpoints by creating the following Kubernetes objects, the namespace=default/name=default for the TLSStore is what Traefik looks for:
Full example for a HTTP-Basic password protected Traefik https endpoint, with 3 replicas round-robin load balanced:
Example of Service + IngressRouteUDP resources for custom UDP Traefik entrypoint: