Codefest CTF 2018 - Write-ups - Part 1

Information#

CTF#

  • Name : Codefest CTF 2018
  • Website : hackerrank.com
  • Type : Online
  • Format : Jeopardy
  • CTF Time : link

50 - Typing Master - Programming#

If you think you have it in you, connect now to 34.216.132.109 9093 and prove your mettle.

You will be presented with a simple typing task which is meant to check your typing speed.

For example, Can you type 'Z' 10 times followed by 'u' 6 times, followed by the sum of their ASCII values?

ZZZZZZZZZZuuuuuu207

I made a ruby script using regex to parse the task question and then generate the answer string:

#!/usr/bin/env ruby
require 'socket'

hostname = '34.216.132.109'
port = 9093

s = TCPSocket.open(hostname, port)

raw = ''
input_flag = false

while chunck = s.read(1)
  print chunck
  raw += chunck
  if /You gotta be fassssssssst :D/.match?(raw)
      input_flag = true
  end
  if input_flag == true
    x, xt, y, yt = raw.match(/.* '([A-Z]{1})' ([0-9]+) times followed by '([a-z]{1})' ([0-9]+) times, .* the sum of their ASCII values/).captures
    answer = x*xt.to_i + y*yt.to_i + (x.ord + y.ord).to_s
    s.puts answer
    puts answer
    input_flag = false
    raw = ''
  end
end

Executing the script I got the flag:

$ ruby typing-master.rb
Give me 'R' 148 times followed by 'k' 169 times, followed by the sum of their ASCII values.
This connection will close in 10 secs ;) You gotta be fassssssssst :DRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk189
 
The flag is: CodefestCTF{1_s33_y0u_4r3_a_m4n_0f_sp33d}

H4k3r has heard that there is a secret hidden behind this website, but he is confused as to how to get access to it. Can you help him.

Making a request to http://34.216.132.109:8084/, we receive a strange Set-Cookie header:

Set-Cookie: Who are you?=Me; Expires=Fri, 31-Aug-2018 21:13:26 GMT; Max-Age=0; Path=/

We always receive You are not authorized for this information, so we need to change that value. Let me guess, something like Who are you?=admin?

I launched Burp Suite and tried that:

The flag was: CodefestCTF{f0r7Un4B1sC0TtO}.

75 - Web BooK - Web#

It is expected to complete reading a book/novel to pass the course, but the students being clever avoid reading the whole book by going through the summary only.

Santosh(their course teacher) comes up with a new idea, he creates a magic book (you can only go to next page, that is: you can't go to next page without reading the previous one and so on, and you can only start from the beginning).

It is know that the flag is hidden somewhere in the book, so the only way to pass the course is to read the whole book, find the flag. The book has 1000 pages so better be fast. And if you are lucky, you may even find the key on the very first page itself.

link to Web_BooK

Output Format

CodefestCTF{flag}

The description of the challenge is pretty clear.

We just need to parse the HTML to find the link of the next page and keep looking at Set-cookie at every page.

So I made a ruby script using http-cookie for handling cookies and nokogiri for parsing HTML by CSS.

#!/usr/bin/env ruby
require 'net/http'
require 'http-cookie'
require 'nokogiri'

base_url = 'http://34.216.132.109:8083'.freeze

uri = URI(base_url + '/fp/')

# Initialize a cookie jar
jar = HTTP::CookieJar.new

flag_found = false

# find next page
def find_np(html)
  doc = Nokogiri::HTML(html)
  form = doc.css('form').first
  next_page = form['action']
end

# Persistent connection
Net::HTTP.start(uri.host, uri.port) do |http|
  # request
  req = Net::HTTP::Get.new uri
  # response
  res = http.request req
  # parse the html to get next page URL
  next_page = find_np(res.body)

  # now try all page until we find the flag
  until flag_found
    uri = URI(base_url + next_page)
    req = Net::HTTP::Get.new uri
    # Get cookie
    res.get_fields('Set-Cookie').each do |value|
      jar.parse(value, req.uri)
    end
    # Use cookie
    req['Cookie'] = HTTP::Cookie.cookie_value(jar.cookies(uri))
    res = http.request req
    # if there is a flag show it
    if /flag/.match?(res.body)
      puts res.body
      flag_found = true
    # else continue browsing
    else
      next_page = find_np(res.body)
    end
  end
end

A good amount of requests later we finally got the page where is hidden the flag.

<!DOCTYPE html>
<html>
<head>
	<title>Web BooK</title>
</head>


<body>
	d5PPc0WZpCXhzQRHraJD8LzcmAioN YV2quFK2v A4dPXM2ti2upY3HLRrHnB0ynJJ h3RtQ GANeJh owD7 3NaoGYiQ1bV uRLTrZz85mbWWDkRbRnceWTtYe oM7ou OYI1AskQN5Pf9XFfeI1WCrZlE8 oyDcR1add ZkR1onQg22s hUBqEuXySydv2vfmplOZLd5c YWRRe75gDciN4 DVKvbcppP7BamQ0 1LrQ1gAuLULUlZz62wgPaHy284T7a 1DKYnrftCujAsWoOB1cnn 3qn3y1gjFaidTkC Dj Oh 2Skj8G3D7WNbj 55Y hqAobXbfGakxtDysYLUwUy DdkCfJY08FKxmofhDSYPj2Xg JIOk9l2kAQxmECuHFhkpmBJVeP ILSPxmAMvKZvhfQQzql3oGI EAKQDHIccnXtRyR0UOcKx22Dxrrf pnBxXX9B I8FLGUcM8kw2E kiS N4fddm2xuOqhKEir74WKaWqiZIwgY sED9Q8YZXqdU DNh8XqHk92cp8zGy7qkDBdbNZWwFNY cEDpOZm6jMToVo575kMAudlsISoCEw IDgXCQ2cmI4whVlWoG8jaal WFTB1y 8pVCXhT7 X omBp7OpvNa4 qqUbkg2OPvE83ygvtET7fsvr H4ZFviB9jmSFWhHer9U2kgzORnI6H ND2aVX7mPPqL0 tFQHWDaudDwgsnp8vL4Z7e QPg2eZqAQH2toG89KQtq3TBht3 fOJ7MaAHxMIQ7WJ40ETEuZBASqOF2 idVXNV8cb73UMWS2m r1hew8Wvyb35yG 4P6j3jp Fv0zZogrtClgY9287S8XQNIZvmaalg 9grVeAn48AaLYFGxg7 Zq37pZdkVR7m7ooI073SKRd8uD P2bhGC2G3k7Wk4ac0TtkHUYG ScxUBShvUTdSW2CivQ60nP1G zEFbcT LjjbkI yzhhnJwi q kLnOdW FedRBO 1kmCE1GekMw47HmYnTGLmELL I9ss2bxvv b6We5BqhUj4b97DVxh 44es87E9IkZmscLZBn1 HjNQtTeVF4QMCDn8SE6D1n3 vFJYmz p1ek8sRJwASZpdx49klzcK tWQ6rULs3wyxKwcRYZU 2XJFaYsnTWWV5YMvlhQNbVlif jizPbtlZHgBh9vHetE53k pdu 4N v5JFAONIT4GRwt jV7UB5tUPfL0GHNYkgAbRss8tPMy jM33LTnqWloqheGAtmfQZktNzf I IWPHjJA9aWmX 9pYOTSDcoPBoK0KPArhduO1 WuXJ9CQ7g30vl c1YtI2 ezxrqJVwJAXGlqsm0ZUOWpl4 68hMZkFp0FuV 8KYLJoJeDblXhHszhYckHa4s6MD9 bdCxTXZH UDopVihTxOo sgeAMduV26NT4hnDgUxR 1TuyBFLeo3llea9uUehWBD lciCZZ JgPUySorOlEEwQf4NAH47nZ q3VA0pd4UTK9ZmgXn0ZqFPBre7lD IafdWFttrZbwvq3a3Q6 RznYJ8u6tDxrdJuCo70IMi87 fTl3ioyaR3sQbcgokNgRznUHVEz0W dEPeMf95aa7rkOqB4sv7Y8qV 6PCopvtluhUWdcrX JZmER2sdqF CvGDQZMDBli1Llc6NxIAWfqe IrvO8xlu4P8vr6ufkmKDG8P gdikw0Y ecfHwIO V9hmhMvwL loeP BE Ud7OmFB149ASQOVlIrOfqW o7ATDlbAVGWyjflV3Nt3uDiyNdmi6 ry7fY O nJ5Sod8WWFLLMwwVEBftpbNRyDo m3qp0qtuI s304Zteiik4 aonVwl HyDo8EGrLTtss xcVjfMP nz3Q2vaeQDIBix4 Fkb62W7pvdDNsnAf3M pmSOPbcYeC d5ugvnFpUaoEVVBXh8sUD8crlqBR8w mer48MWhMdJAyAiauOLKnVeLHjGE17 14b5c5xaQFohMWBfI0Fgdn E0R8VutvJptg5R53MCM Jsa1NFcr8t4aRG 7ke9nowLMNkpUEW76rcE0nffx tsXrbWJgO4iK 8UAkJbfV1bSOi6V8yj2TRtW2eo hwAfj51BbNbNGYyXCBFfyjsOTCdiQG IDv753abzUDZKndPw3HZI BQHWDIG4yjZgmDLGkZ9l cKjG5aVJ7m giXCk30QLLKeYs0 va1cCM9O2a0EF1CrithyXlR h BvO8IDyg4DnAEjGbwdO8wI OBn vWHOr8poc0kJMwAUurPxu2B bns the flag is bAs!c_ScripTing&amp;isn!t(it)
</br>

<form action="/np/VHm4Av4sSR/" method="get">
<button type="submit">Next</button>
</form>

</body>
</html>

Flag was: CodefestCTF{bAs!c_ScripTing&isn!t(it)}.

100 - Access Denied? - Programming#

A school IT staff manages access to secure files by the method of access code. You are required to give your name and the access code, and the program will give out secret information.

It checks whether you already have an access code, generates new random one along with a new user ID alloted to the user, if that user is not found locally on the system. The access codes are known to have random expiration time (don't know what goes on in their minds!), so don't be surprised if you generated an access code just seconds ago and next time the same access code doesn't work.

Johnny decided to go into the IT room and copy the program into his pendrive. You can find it here.

Can you get the secret information out from the program? The service runs on 34.216.132.109 on port 9094.

Source:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import random
import user_functions

user = raw_input("Enter your name: ")

if not user_functions.exists(user):
  # generate a code

  count_ = user_functions.generateID(user)%1000	#User ID/ UID in the table is always positive

  generator = "xorshift"
  random.seed(generator)
  count = 0;

  for ch in user:
    ra = random.randint(1, ord(ch))
    rb = (ord(ch) * random.randint(1, len(user))) ^ random.randint(1, ord(ch))

    count += (ra + rb)/2

  
  code = 1

  for i in range(1,count+count_):
    code = (code + random.randint(1, i) ) % 1000000

  final = random.randint(1,9) * 1000000 + code

  #store it in the database
  user_functions.store(user, final)

else:
  #if user already exists, fetch access code
  final = user_functions.get_code(user)

code = raw_input("Enter your access code: ").strip()


while True:
  
  if code.isdigit():
    if (int(code) == final):
      print "The flag is " + user_functions.get_flag(user)
      exit()
    else:
      print "Incorrect access code"
  else:
    print "The code must be an integer"

  code = (raw_input("\nPlease enter the code: "))

  print "\n###############################################"

We will bruteforce codes because they are based on count_ that can take only 1000 values and because the seed is fixed.

A member of my team (imth) made a python script that I just commented:

#!/usr/bin/env python
from pwn import *
import sys

codes = []
user = ''

# Generates all possible codes
for i in range(0,1000):
    count_ = i

    # the seed is always the same
    generator = "xorshift"
    random.seed(generator)
    count = 0;

    for ch in user:
        ra = random.randint(1, ord(ch))
        rb = (ord(ch) * random.randint(1, len(user))) ^ random.randint(1, ord(ch))

        count += (ra + rb)/2

    code = 1

    for i in range(1,count+count_):
        code = (code + random.randint(1, i) ) % 1000000

    final = random.randint(1,9) * 1000000 + code
    codes.append(final)

# Connect to the server
r = remote('34.216.132.109',9094)
r.recvuntil('Enter your name: ')
r.sendline()

# Now try all codes we previously generated
for x in codes:
    text = r.recv()
    if 'flag' not in text:
        r.sendline(str(x))
    else:
        print(text)
        print(x)
        sys.exit()

Running it we get the flag.

$ python2 access-denied.py
[*] Checking for new versions of pwntools
    To disable this functionality, set the contents of /home/noraj/.pwntools-cache/update to 'never'.
[*] A newer version of pwntools is available on pypi (3.1.0 --> 3.12.0).
    Update with: $ pip install -U pwntools
[+] Opening connection to 34.216.132.109 on port 9094: Done

The flag is CodefestCTF{1_s33_y0u_4r3_a_m4n_0f_r4nd0mn3ss}

9017059
[*] Closed connection to 34.216.132.109 port 9094
Share