Skip to content

Latest commit

 

History

History
77 lines (53 loc) · 1.75 KB

File metadata and controls

77 lines (53 loc) · 1.75 KB

Vulnerable Code

from flask import Flask, request, session, jsonify

app = Flask(__name__)
app.secret_key = "devkey"

projects = {
    "1": {"owner": "alice", "status": "draft"}
}

@app.route("/login", methods=["POST"])
def login():
    session["user"] = request.form.get("username")
    return "Logged in"


@app.route("/create-project", methods=["POST"])
def create():
    pid = request.form.get("id")
    projects[pid] = {
        "owner": session["user"],
        "status": "draft"
    }
    return "Created"


@app.route("/approve", methods=["POST"])
def approve():
    pid = request.form.get("id")
    projects[pid]["status"] = "approved"
    return "Approved"


@app.route("/archive", methods=["POST"])
def archive():
    pid = request.form.get("id")

    if request.headers.get("X-Manager") == "true":
        projects[pid]["status"] = "archived"
        return "Archived"

    return "Forbidden", 403


@app.route("/project")
def project():
    pid = request.args.get("id")
    return jsonify(projects.get(pid))
Reveal Solution

Findings

1. Authentication Bypass
The login endpoint only requires a username and does not verify a password. An attacker can authenticate as any user by simply submitting their username.

2. Missing Authorization in Approval Workflow
Any authenticated user can approve arbitrary projects.

3. Broken Access Control in Archive Function
Manager access is granted via user-controlled X-Manager header.

4. IDOR in Project Access
Users can access arbitrary project data using ?id=.

5. State Transition Bypass
Projects can be approved or archived without workflow validation.

6. Hardcoded Secret Key
The Flask secret key is predictable and exposed.