significant

problem

#!/usr/bin/env python3

from Crypto.Util.number import *
from threading import Thread
from time import time, sleep

from flask import Flask, request, Response, redirect
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
app = Flask(__name__)
limiter = Limiter(
    get_remote_address,
    app=app,
    default_limits=["50000 per hour"],
    storage_uri="memory://",
)


admin_users_init = ["Astro", "Eth007", "Ciaran", "maple3142", "Robin_Jadoul", "tirefire"]
users_db_init = ["boringuser"] + admin_users_init
RESET_DELAY = 600

def reset():
    global users_db, admin_users, p, q, n, phi, e, d
    users_db = list(users_db_init)
    admin_users = set(admin_users_init)
    p = getPrime(1024)
    q = getPrime(1024)
    n = p * q
    phi = (p - 1) * (q - 1)
    e = 17
    if phi % e == 0:
        return
    d = pow(e, -1, phi)

class Restart(Thread):
    def run(self):
        global reset_time
        while True:
            reset()
            while phi % e == 0:
                reset()
            reset_time = time() + RESET_DELAY
            sleep(RESET_DELAY)
        
Restart().start()

def sign(uid):
    return str(pow(uid, d, n))

def current_user():
    uid = int(request.cookies.get("user"))
    idx = pow(uid, e, n)
    return users_db[idx - 1]

@app.route('/', methods=["GET"])
@limiter.limit("2/second")
def index():
    if "source" in request.args:
        return Response(open(__file__).read(), mimetype='text/plain')
    return open("index.html").read()

@app.route('/create', methods=["POST"])
@limiter.limit("2/second")
def create():
    global users_db
    username = request.form['username']
    if username in users_db:
        return "That user already exists!"
    users_db.append(username)
    user_id = len(users_db)
    cookie = sign(user_id)
    ret = redirect(f'/user/{user_id}')
    ret.set_cookie("user", cookie)
    return ret

@app.route('/reset_time', methods=["GET"])
@limiter.limit("2/second")
def reset_time_endpoint():
    return f"Resetting in {int(reset_time - time())} seconds"

@app.route('/user/<path:user_id>', methods=["GET"])
@limiter.limit("2/second")
def view_user(user_id):
    global users_db
    if int(user_id) > len(users_db):
        return "This user doesn't exist!"
    username = users_db[int(user_id) - 1]
    ret = f'''<h1>{username}</h1>
    You are {"not " if username != current_user() else ""}this user.'''
    if username == current_user() and username in admin_users:
        ret += f" {open('flag.txt').read()}"
    return ret

if __name__ == "__main__":
    app.run('0.0.0.0', 13003)

solution

see the insignificant challenge before this one to understand

here, there is no vulnerability of 1^x=1 given x!=0. however, what we can do is set the user id to 0 because 0^x=0 given x!=0
now, users_db[0 - 1] == users_db[-1] which is tirefire assuming no other users have been created. luckily, the users_db resets every 600 seconds, so it is very easy.

image