apps/sqli/labs/error.py · view on GitHub
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | """SQLi lab: error — INTENTIONALLY VULNERABLE. Login form whose handler concatenates both username and password into the SQL and helpfully renders the raw exception when the query fails. The exception text on MariaDB includes whatever value the attacker forced into the error message, so EXTRACTVALUE/UPDATEXML-style extraction works. """ from __future__ import annotations from pathlib import Path import pymysql from flask import Blueprint, render_template, request from ..db import get_conn bp = Blueprint("sqli_error", __name__, url_prefix="/error") META = { "slug": "error", "title": "Error-based SQLi (login)", "summary": "Login query concatenates user input AND the app renders raw SQL errors.", "hint": ( "Query: SELECT id, role FROM users WHERE username='<u>' AND " "password='<p>'. SQL errors are shown verbatim. Use EXTRACTVALUE: " "username=' AND EXTRACTVALUE(1, CONCAT(0x7e, (SELECT value FROM " "secrets WHERE name='sqli-error')))-- " ), "sink": "string-concatenated SELECT + raw exception render", "source_path": str(Path(__file__).resolve()), "vulnerable": True, } @bp.route("/", methods=["GET", "POST"]) def lab(): username = request.values.get("username", "") password = request.values.get("password", "") result = error = query = None if request.method == "POST" and (username or password): # INTENTIONAL: both fields concatenated into SQL. query = ( f"SELECT id, role FROM users " f"WHERE username='{username}' AND password='{password}'" ) try: with get_conn().cursor() as cur: cur.execute(query) row = cur.fetchone() if row: result = f"Welcome, user id={row[0]}, role={row[1]}." else: result = "Invalid credentials." except pymysql.MySQLError as e: # INTENTIONAL: full exception in the response. error = f"{type(e).__name__}: {e}" return render_template( "lab_error.html", meta=META, username=username, result=result, error=error, query=query, ) |