247CTF - Easy Web Challenge Writeups

Secured session

If you can guess our random secret key, we will tell you the flag securely stored in your session.

Given the source code:

import os
from flask import Flask, request, session
from flag import flag

app = Flask(__name__)
app.config['SECRET_KEY'] = os.urandom(24)

def secret_key_to_int(s):
    try:
        secret_key = int(s)
    except ValueError:
        secret_key = 0
    return secret_key

@app.route("/flag")
def index():
    secret_key = secret_key_to_int(request.args['secret_key']) if 'secret_key' in request.args else None
    session['flag'] = flag
    if secret_key == app.config['SECRET_KEY']:
      return session['flag']
    else:
      return "Incorrect secret key!"

@app.route('/')
def source():
    return "%s" % open(__file__).read()

if __name__ == "__main__":
    app.run()

We can see two URL decorators:

  • @app.route("/flag"): Where the function index() is registered for the route "/flag" so that when this route is requested, index() is called.
  • @app.route('/'): Where the function source() is registered and returns the source code itself when requested.

As you can see the functions index() and source() are never called directly in the code, and will only be executed when an HTTP request is done against the endpoints flag and / respectively.

Basically, what we have to do is a request to /flag and the website will add the flag's content to our cookies, however, it is encoded with JWT and base64, decoding it, it returns the flag.


Trusted Client

Developers don't always have time to setup a backend service when prototyping code. Storing credentials on the client side should be fine as long as it's obfuscated right?

Given the website:

We can inspect the source code by pressing Control + U:

And we see the following function:

<script>
window.onload=function() {
  document.getElementById('login').onsubmit=function() {
    [][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+

    [...snip..]()
    
  return false;
  }
}
</script>

From experience with previous CTF challenges I have completed, it is indeed JSFuck. By googling up "JSFuck decode" we come up with several websites that might work, using https://enkhee-osiris.github.io/Decoder-JSFuck/ and pasting the JSFuck encoded string (make sure to remove the last () as it's the function parenthesis and untick the "With eval" feature), it outputs:

function anonymous() {
    if (this.username.value == 'the_flag_is' && this.password.value == '247CTF{6c91[redacted]0148}') {
        alert('Valid username and password!');
    } else {
        alert('Invalid username and password!');
    }
}