×

php · level 3 · unit 5 · lesson 1

  1. meet it
  2. guess first
  3. your turn
  4. fix it
  5. nailed it

Tap a green word if you get lost.

meet it

See SQL injection work, and you will never glue SQL again.

Treat every form field, link and file as . Most visitors are kind, but an attacker sends a on purpose: text built to break in. Here the payload ' OR '1'='1 lands in a login query glued together with ..

The quote ends your string early, and the rest becomes SQL that is always true. Every row matches, so the attacker is in without the password. Placeholders cure this, but they only hold values. A column name for sorting must come from an of names you wrote yourself.

<?php
$db = new PDO("sqlite::memory:");
$db->exec("CREATE TABLE users (name TEXT, password TEXT)");
$db->exec("INSERT INTO users VALUES ('mia', 'hunter2')");
$_POST = ["name" => "mia", "password" => "' OR '1'='1"];
$sql = "SELECT COUNT(*) FROM users WHERE name = '" . $_POST["name"]
    . "' AND password = '" . $_POST["password"] . "'";
echo $sql . "\n";
$found = $db->query($sql)->fetchColumn();
echo "Matching users: $found\n";

fetchColumn() hands back the first value of the next row, which is ideal for a COUNT(*).