""" vulnerable-webapp.py.txt ======================== INTENTIONALLY VULNERABLE Flask web application for CTF / code-auditing practice. DO NOT deploy or run in production. All vulnerabilities are educational. """ import os import pickle import base64 import sqlite3 from flask import Flask, request, render_template_string, send_file, redirect, session app = Flask(__name__) app.secret_key = "supersecret123" # TODO: fix this later # ---------- Database Setup ---------- DATABASE = "app.db" def get_db(): conn = sqlite3.connect(DATABASE) conn.row_factory = sqlite3.Row return conn def init_db(): db = get_db() db.execute(""" CREATE TABLE IF NOT EXISTS users ( id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT UNIQUE, password TEXT, role TEXT DEFAULT 'user' ) """) db.execute(""" CREATE TABLE IF NOT EXISTS posts ( id INTEGER PRIMARY KEY AUTOINCREMENT, author TEXT, title TEXT, body TEXT ) """) # Hardcoded admin credentials -- TODO: fix this later db.execute( "INSERT OR IGNORE INTO users (username, password, role) VALUES (?, ?, ?)", ("admin", "admin123", "admin") ) db.commit() init_db() # ---------- Hardcoded Credentials ---------- API_KEY = "sk-live-4f3c2b1a0d9e8f7c6b5a4d3e2f1a0b9c" # TODO: move to env ADMIN_PASSWORD = "Passw0rd!" # TODO: fix this later DB_CONNECTION_STRING = "postgresql://appuser:s3cretDBpass@10.0.0.5:5432/production" # ---------- Routes ---------- # VULNERABILITY: SQL Injection (string concatenation) @app.route("/login", methods=["GET", "POST"]) def login(): if request.method == "POST": username = request.form.get("username", "") password = request.form.get("password", "") db = get_db() # Vulnerable: string formatting in SQL query query = f"SELECT * FROM users WHERE username = '{username}' AND password = '{password}'" user = db.execute(query).fetchone() # TODO: fix this later if user: session["user"] = username session["role"] = user["role"] return redirect("/dashboard") return "Invalid credentials", 401 return '''
''' # VULNERABILITY: XSS (unescaped user input in template) @app.route("/search") def search(): query = request.args.get("q", "") db = get_db() results = db.execute( "SELECT * FROM posts WHERE title LIKE ?", (f"%{query}%",) ).fetchall() # Vulnerable: user input rendered directly into HTML without escaping html = f"""