insignificant
problem
source code:
#!/usr/bin/env python3
from Crypto.Util.number import *
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://",
)
users_db = ["admin"]
p = getPrime(1024)
q = getPrime(1024)
n = p * q
phi = (p - 1) * (q - 1)
e = 65537
d = pow(e, -1, phi)
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('/user/<path:user_id>', methods=["GET"])
@limiter.limit("2/second")
def view_user(user_id):
global users_db
username = users_db[int(user_id) - 1]
ret = f'''<h1>{username}</h1>
You are {"not " if username != current_user() else ""} this user.'''
if username == "admin" and current_user() == "admin":
ret += f" {open('flag.txt').read()}"
return ret
if __name__ == "__main__":
app.run('0.0.0.0', 13001)
solution
here, we can see that the user has to be admin to get the cookie. the admin is the only one
because of this:
def current_user():
uid = int(request.cookies.get("user"))
idx = pow(uid, e, n)
return users_db[idx - 1]
we can see that the cookie user
has to be an integer, uid, to the power of e, and then modulo’d by n.
for value admin
to be returned by this function, the variable idx has to be 1
because users_db[1 - 1]
is admin.
there is a problem here, because 1^x
is always 1 unless x is 0 (which it isn’t). therefore, a user cookie of 1 does the trick.