# Custom CTF Platforms Pt 2 This is part 2 of the Custom CTF Platforms posts, where I explain some of the features and mistakes I made in the CTF platforms I have created this is currently running at http://ctf.librondo.so/ # The Newest Platform This platform was created about 2 years after my first platform, my friends and I had messed with a few other versions in between these two, however this one contains most of the features of all the platforms combined. When I started this version, CTFd 1.0 still hadn't been released yet, I don't exactly remeber correctly if ctfs were using a beta version of CTFd but I would imagine so. My original team "Some Assembly Required" all graduated high school and we slowly stopped playing ctfs together and I did pretty much all the development for this final version, however my teammates helped out a lot in the prior version so I luckly did not have to do as much front end development. Since I was mostly working alone, I neglected good development practices and only made 3 commits. ![[Pasted image 20210818205000.png]] ## Features Because most of the design was created as a group with my teammates, I think the overall design looks much better than the orginal blue theme. ### Main Page ![[Pasted image 20210818205443.png]] We had a navbar containing links to: - Challenges - Scoreboard - News - About - Learn - Login - Register ### Register Page A couple extra fields were added since the first version. An affliation field and a password confirmation field. ![[Pasted image 20210818210525.png]] Now, we added some restrictions to teamname and password and had a check for a valid email address. Creating a team redirects to the main page and has a little notice saying team created. Not sure why I removed email verification. ### Reset Password Theres a reset page as well but was unimplemented. ![[Pasted image 20210818211844.png]] ### Login Page Login Page was a seperate page unlike the orginal version where you could login from any page. ![[Pasted image 20210818212013.png]] Logging in redirects to the challenges page. ## Challenges Page Again, challenge categories were hardcoded. ![[Pasted image 20210818212155.png]] A graph at the top was added to show solve counts for each challenge. Clicking a challenge box this time lead to a challenge page. ![[Pasted image 20210818212432.png]] A graph was added to show correct/incorrect submissions and this time individual flag submission forms and hints button. ![[Pasted image 20210818212552.png]] The schema for a challenge is: ```ruby create_table "challenges", force: true do |t| t.string "title" t.string "description" t.integer "value" t.string "hint" t.integer "solves" t.integer "submits" t.string "category" t.datetime "created_at" t.datetime "updated_at" end ``` And there was a relationship with the teams table: ```ruby create_table "team_challenges", force: true do |t| t.integer "team_id" t.integer "challenge_id" t.datetime "created_at" t.datetime "updated_at" end ``` Notice how a challenge record does not include a flag. I don't know why I didn't create a real relationship between a challenge and a flag. The flag structure was: ```ruby create_table "flags", force: true do |t| t.string "grader" t.integer "challenge_id" t.datetime "created_at" t.datetime "updated_at" end ``` A flag was associated to a challenge by its challenge id and contained a path to a grader. A grader was created for each challenge. An example of a grader is: ```ruby class Grader def check(guess) guess = guess.downcase if guess=="flag{therac-25}" return true elsif guess == "flag{therac 25}" return true elsif guess == "flag{therac25}" return true elsif guess=="therac-25" return true elsif guess == "therac 25" return true elsif guess == "therac25" return true else return false end end end ``` This allowed for multiple ways to validate if a flag could be correct. An example of creating a challenge through ruby is: ```ruby Challenge.create("title"=>"Song of my People","description"=>"I am a <a href='/challenges/songofmypeople.wav' target='_blank'>Robot</a>","hint"=>"I speak 1s and 0s","value"=>175,"solves"=>0,"category"=>"Misc").flag = Flag.create("grader"=>"songofmypeople.rb") ``` From the solves list on the challenge page, you can navigate to their team page. ### Team Page Team Page contains a couple graphs and a list of the solved challenges. ![[Pasted image 20210818213831.png]] ![[Pasted image 20210818213849.png]] The challenge links back to the challenge page. ### Scoreboard The scoreboard shows a graph of the solve times of the top 5 players. The admin account is shown on the graph but hidden on the scoreboard. ![[Pasted image 20210818214209.png]] Clicking a team on the scoreboard links to their team page. ### News The news schema is pretty similar to the orginal version but an author field is added: ```ruby create_table "news", force: true do |t| t.string "author" t.string "title" t.string "text" t.datetime "created_at" t.datetime "updated_at" end ``` ![[Pasted image 20210818214559.png]] Not sure why I flipped it this time and newer posts were placed at the bottom. ### About About page just had info about what is a ctf and what the rules were. ### Learn Taking from picoCTF, where they had a learn page. We attempted to write a little about each category. Pretty much none of this information is useful. ![[Pasted image 20210818214836.png]] ## Lessons Learned I hate webdev, still missing a lot of features that standard for most ctf platforms. Ruby on Rails is pretty cool and as much as I hate webdev, I sorta want to work with Rails and see what cool features they have added in the past few years. We never ran a real ctf off this platform so who knows what bugs and edge cases I missed. Still need an admin panel, I actually had some code set up for an admin panel but really never implemented anything. ```ruby <% if current_team %> <li><a style="color: #C90000" href="/team/<%=current_team.id%>"> <%=current_team.name%> : <%=current_team.score%> points </a></li> <li> <a href="/logout" class="nav_link" >logout</a></li> <% if current_team.is_admin==1 %> <li><a href="/admin">Admin Panel</a></li> <%end%> <%else%> ```