Неправильно думать, что вам нужно беспокоиться только о пользовательском вводе.
Ваш код может получать небезопасный контент из любого источника, например:
- Чтение файлов
- Открытие URL-адреса, например, вызов веб-службы
- Чтение из вашей собственной базы данных
Правильно, даже данные, которые были безопасно вставлены в вашу собственную базу данных, могут стать небезопасным контентом.
Пример. Предположим, вы хотите найти всех пользователей, имена которых совпадают с именем пользователя 123 (я знаю, что это можно сделать с помощью JOIN, но это всего лишь пример, так что потерпите меня):
$name = $conn->query("SELECT name FROM users WHERE id=123")->fetchColumn();
$data = $conn->query("SELECT * FROM users WHERE name = '$name'")->fetchAll();
Это безопасно?$name
- это что-то, что я достал из базы данных, и мы предполагаем, что он был благополучно вставлен ранее.Как данные в моей собственной базе данных могут представлять риск для SQL-инъекции?
Что если имя «O'Reilly»?Это приведет к тому, что второй запрос будет иметь синтаксическую ошибку по крайней мере, потому что одинарные кавычки будут несбалансированными.
Это технически SQL-инъекция, хотя риск, скорее всего, будет простой ошибкой, чем любая зловещая попытка взлома.
С другой стороны, были реальные случаи, когда хакер намеренно регистрировалсяих «имя» на веб-сайте таким образом, что он использовал SQL-инъекцию или межсайтовый скриптинг.Когда имя злоумышленника позже использовалось веб-сайтом в каком-либо другом запросе или веб-выводе, он успешно завершил взлом.Я не шучу.
Решение, как обычно, заключается в использовании подготовленного оператора с параметром запроса:
$stmt = $conn->prepare("SELECT * FROM users WHERE name = ?");
$stmt->execute([$name]);
$data = $stmt->fetchAll();
Предположение, что SQL-инъекция происходит только из пользовательского ввода, напоминает мнеэтой цитаты:
«Объяснения существуют; они существовали всегда; всегда есть хорошо известное решение для каждой человеческой проблемы - аккуратное, правдоподобное и неправильное».- HL Mencken