← articles

web · database · injection

SQL injection: authentication bypass with a single quote

User input concatenated into a query becomes part of the SQL.

When input is concatenated into a SQL string, it can change the structure of the query, not just its values.

SQL injection live demo
acme-portal · /login
SELECT * FROM users WHERE name = 'alice' AND pass_hash = ''

Your input lands inside the query. Try a quote.

Submit the form.
Simulated. Runs entirely in your browser.

The bug

q := "SELECT * FROM users WHERE name = '" + name + "' AND pass_hash = '" + hash + "'"

With name set to admin' --:

SELECT * FROM users WHERE name = 'admin' --' AND pass_hash = '…'

The quote closes the string literal, and -- turns the password check into a comment.

Beyond login

  • UNION-based extraction of other tables.
  • Blind injection (boolean or time-based) when nothing is reflected in the response.
  • Stacked queries, where the driver allows several statements per call.
  • File access or command execution, depending on the DBMS and the account’s privileges: xp_cmdshell on SQL Server, COPY ... PROGRAM for a PostgreSQL superuser.

Where it still appears

ORMs and query builders cover the common path. What remains:

  • Identifiers (ORDER BY columns, table names), which cannot be bound as parameters.
  • Raw SQL escape hatches in ORMs.
  • Search and filter builders, report generators.
  • Second-order injection: a value stored safely, then concatenated into a later query.

Fix

Bind parameters, so the query structure is fixed before the data arrives:

var id int64
var hash []byte
err := db.QueryRowContext(ctx,
	"SELECT id, pass_hash FROM users WHERE name = $1", name,
).Scan(&id, &hash)

Then verify the password in code with bcrypt or Argon2id, not in SQL.

Identifiers come from an allow-list:

columns := map[string]string{"date": "created_at", "total": "amount"}
col, ok := columns[r.URL.Query().Get("sort")]
if !ok {
	col = "created_at"
}

Run the application with a database role that has only the privileges it needs.

I test web apps, APIs and LLM integrations. Contact.