SQL Injection

Вредоносный SQL код вставляется в запрос, чтобы выполнить любые команды базы данных, на которые у пользователя есть привелегии.

Например, в запросе SELECT * FROM users WHERE username=’$user’ злоумышленник может передать ' или "=' для поля $user, чтобы увидеть все данные в таблице users.

Такое поведение можно предотвратить, используя prepared statements или специфичные для базы функции экранирование, такие как например mysqli_real_escape_string().

Например, есть форма логина:

<form method="login.php" action="POST">
    Username: <input type="text" name="username" />
    <br />
    Password: <input type="password" name="password" />
    <br />
    <input type="submit" value="Log In" />»
</form>

и код, который выполняет вход на основе данных из этой формы:

$username = $_POST['username'];
$password = password_hash(
    $_POST['password'], PASSWORD_DEFAULT
);

$sql = "SELECT *
        FROM   users
        WHERE  username = '{$username}' AND
               password = '{$password}'";

/* database connection and query code */

if (count($results) > 0) {
   // Successful login attempt
}

В данном примере нет фильтрации входных данных из POST. Вместо этого сырые введенные данные вставляются в переменную $username. Затем этот ввод используется в SQL-выражении. Злоумышленник может попытаться залогиниться, используя такой логин:

username' OR 1 = 1 --

С этим логином и пустым паролем SQL-выражение теперь имеет вид:

SELECT *
    FROM users
    WHERE
        username = 'username' OR 1 = 1 --' AND
        password =

А так как 1=1 всегда будет TRUE а строка -- начинает комментарии в SQL-выражении, то все после них будет проигнорировано и в результате будут успешно возвращены все записи из таблицы.

Подобного рода атаки становятся возможными из-за отсутствия фильтрации и экранирования входных данных. Чтобы обезопасить себя следует использовать prepared statements в своем приложении или экранировать данные.