Flag Authoriser (net)

PUBLISHED ON 30/11/2021 — EDITED ON 11/12/2023 — 247CTF, INFOSEC


A little write up of a Networking challenge The Web Shell on the CTF site


Can you forge a new identity to upgrade your access from an anonymous user to an admin?



The challenge provide us with the following code:

from flask import Flask, redirect, url_for, make_response, render_template, flash
from flask_jwt_extended import JWTManager, create_access_token, jwt_optional, get_jwt_identity
from secret import secret, admin_flag, jwt_secret

app = Flask(__name__)
cookie = "access_token_cookie"

app.config['SECRET_KEY'] = secret
app.config['JWT_SECRET_KEY'] = jwt_secret
app.config['JWT_TOKEN_LOCATION'] = ['cookies']
app.config['DEBUG'] = False

jwt = JWTManager(app)

def redirect_to_flag(msg):
    flash('%s' % msg, 'danger')
    return redirect(url_for('flag', _external=True))

def my_expired_token_callback():
    return redirect_to_flag('Token expired')

def my_invalid_token_callback(callback):
    return redirect_to_flag(callback)

def get_flag():
    if get_jwt_identity() == 'admin':
        return admin_flag

def flag():
    response = make_response(render_template('main.html', flag=get_flag()))
    response.set_cookie(cookie, create_access_token(identity='anonymous'))
    return response

def source():
    return "


" % open(__file__).read()

if __name__ == "__main__":


Reviewing the code shows us that we are looking at Flask webapp using some JWT (JSON Web Tokens). We need to hit the /flag, and to obtain it we need to have identity parameter set to admin.

So search for JWT vulnerabilities.

It is all about JWT!

First we need to obtain a valid JWT cookie from the site:

curl -c - https://xxx/flag

We get a base64 encoded string, that can be pasted into a tool like

  "alg": "HS256",
  "typ": "JWT"
  "csrf": "c74e65f2-e234-45d6-bddf-fb59e4915c74",
  "jti": "d21963e3-9241-42d8-bd46-9c2efc662f58",
  "exp": 1638045444,
  "fresh": false,
  "iat": 1638044544,
  "type": "access",
  "nbf": 1638044544,
  "identity": "anonymous"

Okay, simple stuff, change the identity and resend the token.

But there is still another thing we need to do to make it. The token in this case is signed and when we modify it, we need to sign it again to make it valid.

Breaking the secret key

Take the encoded token and save it as jwt.txt. Break the secret signing key with John The Ripper:

$ john jwt.txt --wordlist=rockyou.txt --format=HMAC-SHA256
$ john --show jwt.txt

Forging the token

Take the token, plug it again in

Add the secret.

We know we need the identity needs to be admin so set that up in the parameters.

Submitting our forgery

Take the base64 encoded token, use Cookie Quick Manager in Firefox to edit it, paste in the forged token instead of the provided one and voilà.

Other useful tools