Category: Web Points: 75 Solves: 22 Description:

    What does this service do? It hides a flag!

 

Navigating to the website, we see an input box and a query button. The first thing to do is throw some data at it and see what happens:

 

SENT: a
RESPONSE: 61008ce2,CAMP15_silverneedle
RESPONSE: 61010292,CAMP15_silverneedle
SENT: ab
RESPONSE: 61626b8f,CAMP15_silverneedle
RESPONSE: 6162dc3f,CAMP15_silverneedle
SENT: abc
RESPONSE: not found

 

I initially verified using Burp Suite that the data coming back was what was expected. Indeed, the javascript on this page simply takes user input, sends it over the websocket, and prints whatever the server sends back. Also, based on a little playing around, it seems that not all combinations are valid.

 

My initial thought was to simply brute force the space with python using a depth first search. I used depth first because it clearly looked like there were not going to be long strings of requests that were valid:

 

#!/usr/bin/python3

from websocket import create_connection
import string

def isNeedle(s):
        ws.send(s)
        o = ws.recv()
        if o == "not found":
                return False
        o2 = ws.recv()
        if "CAMP15_silverneedle" not in o or "CAMP15_silverneedle" not in o2:
                print("Golden Needle?: {0}".format(s))
                exit()
        return True

ws = create_connection("ws://challs.campctf.ccc.ac:10116/q")

def tryCombinations(b=""):
        for c in string.printable:
                print("trying {0}".format(b+c))
                if isNeedle(b + c):
                        tryCombinations(b+c)


tryCombinations()

 

While the concept would work, I got tired of waiting and watching. Looking a little more closely at the responses, what we're getting back with a successful query are, at the minimum, the characters that we gave to the system in hex format. For instance, the first query of a came back as 61008ce2. Note that "0x61" is the ascii encoding for "a". With that in mind, the second question was why were we getting back two responses? My guess was that this was similar to a linked list, where the first number was possibly the closest value to whatever you put in, and the second was the next number in the list. If true, this would allow us to walk down the linked list until we found the golden needle.

 

#!/usr/bin/python3

from websocket import create_connection
import string
from binascii import unhexlify

def followNeedles(s=b'\x94\xe2\xdf!'):
        while True:
                ws.send(s)
                print("Trying: {0}".format(s))
                o = ws.recv()
                if o == "not found":
                        print("Not found error...")
                        return False
                o2 = ws.recv()
                #print("{0} valid".format(s))
                if "CAMP15_silverneedle" not in o or "CAMP15_silverneedle" not in o2:
                        print("Golden Needle?: {0}\n{1}\n{2}\n".format(s,o,o2))
                        exit()
                s = unhexlify(o2.split(",")[0])


ws = create_connection("ws://challs.campctf.ccc.ac:10116/q")

followNeedles()

 

It was indeed true. After a little while of waiting, we found:

 

Trying: b'\x94\xe2\xdf!'
Golden Needle?: b'\x94\xe2\xdf!'
94e2df21,CAMP15_foobar_golden
94e44d19,CAMP15_silverneedle

 

Flag: CAMP15_foobar_golden