Learn by Directing AI
All materials

remediation-guidance.md

Remediation Guidance — SQL Injection

Finding: SQL injection in the web application's input handling Severity: Critical Reference: ATT&CK T1190 / OWASP A03:2021


Root Cause

User input from the booking form's query parameter is concatenated directly into SQL queries without sanitization or parameterization. The application constructs queries by embedding user-supplied values into the SQL string:

$query = "SELECT * FROM users WHERE user_id = '$id'";

An attacker can inject SQL syntax through the input field, causing the database to execute unintended commands. This exposes the entire guest database — names, email addresses, phone numbers, and passport numbers.

Approach A: Prepared Statements with Parameterized Queries

Use mysqli_prepare() with bound parameters. The database engine receives the query structure and the parameter values separately. The parameter is always treated as data, never as SQL syntax, regardless of what characters it contains.

$stmt = $conn->prepare("SELECT * FROM users WHERE user_id = ?");
$stmt->bind_param("s", $id);
$stmt->execute();

This approach eliminates SQL injection at the root — the database cannot interpret the parameter as part of the query structure. It works for all input types and does not depend on correctly identifying dangerous characters.

Approach B: Character Escaping

Functions like mysqli_real_escape_string() attempt to neutralize special characters by escaping them before they reach the database:

$id = mysqli_real_escape_string($conn, $id);
$query = "SELECT * FROM users WHERE user_id = '$id'";

This approach has known limitations. It can be bypassed in specific scenarios: numeric injection where the parameter is not enclosed in quotes, multi-byte character set attacks where the escaping function does not account for the connection's character encoding, and edge cases where the function does not escape all relevant characters for the specific database configuration. AI tools frequently suggest this approach because it requires fewer code changes. It is simpler but not equivalent in protection.

Verification

After applying a fix, re-run the exact sqlmap command that succeeded during exploitation. This is the definitive test:

  • If sqlmap still reports the parameter as injectable, the fix is insufficient. The vulnerability remains exploitable regardless of the code change.
  • If sqlmap reports the parameter is not injectable, the fix blocks the attack vector.

Also verify that the application still functions normally after the fix. Load the booking form and submit a legitimate query. A fix that breaks the application's core functionality is not a viable remediation — guests need to be able to search and book.