Breaking the Quiz Bot- Capture the Flag

Ujjayanta Bhaumik
4 min readJan 10, 2021

Capture the Flag is an information security competition where questions are asked from various categories like:

  1. Cryptography
  2. Steganography
  3. Web Technology etc

You have to solve puzzles to get prizes called flags. The flags are generally hidden in plain sight. Recently, I participated in the winter edition of BrixelCTF(https://ctf.brixel.space/)

I would share one of the ‘flag’ stories today. The story is about a Quiz bot. Long, long time ago — well, not so long ago, I went to the website: http://timesink.be/quizbot/

You had to answer 1000 questions correctly, one after one, and get the flag. Also, no mistakes! You had to get 1000 correct answers in a row.

Well, at first, I googled and started putting the answers. But after 5 or 6 tries, I gave up- can’t do that 1000 times. After spending some time on the page, I found out that, if I do not write anything in the text box and click answer, the page just said “wrong answer” and gave me the answer.

This taught me that: to beat the bot, I needed to write a script that just put a blank string ‘’ in the text box and pressed submit. After 1000 iterations, I would get all the correct answers. After that, I just had to submit the correct answers one by one using a script to get the flag.

For automation stuff, Selenium is often the first choice. But, I used the mechanize library for this task.

___________________________________________________________________

The code is pretty simple.

import mechanize
br = mechanize.Browser()
#Here the mechanize library is initialized and a browser instance is #created.
br.open("http://timesink.be/quizbot/?action=send")
br.select_form(nr=0)
#br.open opens the quiz bot website “http://timesink.be/quizbot” and #select_form is used to select the HTML form in the page.
br.form['insert_answer'] = ' '
#pass blank string to the text box. The text box id is 'insert_answer' which I found by inspecting the page
req = br.submit()
#submitting the blank string
content = req.read()
print(content)
ss = str(content)

The string stored in ss is something like this:

b'<div align="center">Wrong Answer! The answer is: </div><div id="answer" align="center">beach boys</div>\n<div align="center"><h1>QuizB0t!</h1><br>Can you beat the 1000 questions?<br>Score: 0&nbsp;&nbsp;&nbsp;(<a href="index.php?resetscore">Reset progress</a>)<br></div>\n<div align="center">\n<h3>Question number 2</h3>\n<h4>How many rings on the Olympic flag ?</h4>\n<form method="POST" action="index.php"><input type="text" name="insert_answer" id="insert_answer"><input type="submit" name="submit" value="answer"></form>\n</div>\n'

The bold part showing beach boys is the region of interest and we need to extract this string from ss. Let’s split ss by ‘>’. We get a list:

['b\'<div align="center"',  
'Wrong Answer! The answer is: </div',
'<div id="answer" align="center"',
'beach boys</div',
'\\n<div align="center"',
'<h1',
........
]

We can see that the fourth element or ss.split(‘>’)[3] is ‘beach boys</div’

Again split ‘beach boys</div’ by ‘<’. ss.split(‘>’)[3].split(‘<’) gives us the list: [‘beach boys’, ‘/div’]

Therefore, ss.split(‘>’)[3].split(‘<’)[0] gives beach boys, the correct answer to the question, ‘Carl and the Passions changed band name to what ?’ We can keep following this method and get the correct answer for each question.

import mechanize
br = mechanize.Browser()
answers = []
for i in range(0,1001):
br.open("http://timesink.be/quizbot/?action=send")
br.select_form(nr=0)
br.form['insert_answer'] = ' '
req = br.submit()
content = req.read()
ss = str(content)
#print(ss.split('>')[3].split('<')[0])
answers.append(ss.split('>')[3].split('<')[0])

Here, we are just storing the correct answers in the answers array.

aa = answers[0:1000]
#Just making a copy of the first 1000 elements of the answers array as we need 1000 answers
import mechanize
br = mechanize.Browser()
for i in range(len(aa)):
br.open("http://timesink.be/quizbot/?action=send")
br.select_form(nr=0)
print(aa[i])
br.form['insert_answer'] = aa[i].replace('\\', '')
req = br.submit()
content = req.read()
print(content)

Now, let’s go line by line.

import mechanize
br = mechanize.Browser()

Here the mechanize library is initialized and a browser instance is created.(For detailed information, please see: https://mechanize.readthedocs.io/en/latest/browser_api.html)

br.open("http://timesink.be/quizbot/?action=send")
br.select_form(nr=0)

br.open opens the quiz bot website “http://timesink.be/quizbot” and select_form is used to select the HTML form in the page.

br.form['insert_answer'] = aa[i].replace('\\', '')

In this line, I did some preprocessing, as Python stores strings like ruth’s as ruth\’s. So, I replaced the \ with a blank space.

req = br.submit()
content = req.read()
print(content)

In these lines, I just submit the ith string in the array aa and get the content from the page. The outside for loop iterates this whole process.

Finally, the output is:

You can see the flag in the selected line: brixelCTF{kn0wl3dg3}

Thank you for reading.

--

--

Ujjayanta Bhaumik

MSc Computer Vision, Graphics and Imaging, University College London