Что такое sql инъекция?
Увидел в профиле модератора EnSO - Dharman следующее предупреждение:
Свободный перевод:
Предупреждение:
Вы широко открыты для SQL-инъекций и должны использовать параметризованные подготовленные операторы вместо ручного построения ваших запросов. Они предоставляются PDO или MySQLi. Никогда не доверяйте никаким входным данным! Даже если ваши запросы выполняются только доверенными пользователями, вы все равно рискуете повредить свои данные. Экранирования недостаточно!
Если модератор посчитал важным, размещая в своем профиле это предупреждение для того, чтобы это увидело, как можно большее количество людей, то меня естественно заинтересовал вопрос, что это за зверь SQL Injections и всё остальное, что с этим связано:
Из описания метки MySQLi
Расширение драйвера реляционных баз данных, используемого в языке программирования PHP для предоставления доступа к базам данных MySQL. MySQLi является обновлённой версией драйвера PHP MySQL, и даёт различные улучшения в работе с базами данных.
Хочу получить более развернутый ответ.
Как реализуется защита, желательно наличие примеров с краткими поясняющими комментариями.
Ответы (2 шт):
SQL-инъекция — это обычный способ взлома, при котором хацкер может подсунуть в твою базу данных что угодно, просто введя хитрую строку вместо обычного текста.
Такое происходит, когда ты доверяешь пользовательскому вводу и вставляешь его прямо в запросы к базе. Это может привести к потере данных или даже полному контролю хацкерами.
А чтобы защититься, нужно использовать подготовленные запросы: это способ сказать базе: "вот структура запроса, а вот данные отдельно". Тогда даже если кто-то попытается ввести что-то вредное, оно просто будет воспринято как обычный текст, а не как целая команда. Экранирование вручную тут не поможет, потому что это всё равно как приклеить дверь скотчем вместо того чтобы её закрыть на замок.
Объясню на примере майнкрафт сервера:
Предположим, что у меня есть база данных для хранения информации о игроках. Когда игроки заходят на сервер, их имя и другие данные сохраняются в базе. Если я буду просто брать имя игрока и вставлять его в запрос без проверки, хацкеры могут использовать SQL-инъекции.
Например, если я вставлю имя игрока прямо в запрос, как это:
"INSERT INTO players (name) VALUES ('игрок');"
Хацкер может ввести что-то вроде этого в своё имя:
"игрок'); DROP TABLE players; --"
Тогда запрос превратится в:
"INSERT INTO players (name) VALUES ('игрок'); DROP TABLE players; --');"
Этот запрос сначала вставит имя, а затем выполнит команду:
DROP TABLE players;
, которая удалит таблицу с игроками, что приведёт к потере данных.
Чтобы избежать этого, я использую подготовленные запросы. Это значит, что я сначала создаю запрос с пустыми местами для данных, а затем отдельно вставляю данные. Таким образом, база данных понимает, что это просто данные, а не часть запроса.
Полный пример с подготовленным запросом на моём сервере:
// Получаем имя игрока
String playerName = getPlayerNameFromInput();
// Запрос с подготовленным местом для данных
String query = "INSERT INTO players (name) VALUES (?)";
// Создаём подготовленный запрос
PreparedStatement stmt = connection.prepareStatement(query);
// Вставляем данные безопасно
stmt.setString(1, playerName);
// Выполняем запрос
stmt.executeUpdate();
Таким образом, даже если кто-то попытается вставить вредоносный код через ник, пароль и т.д., это будет воспринято как обычный текст, и ничего не произойдёт
Конечно, можно использовать параметрические запросы (что правильно с точки зрения оптимизации и кеширования запросов движками БД). А можно использовать функции чистки типа mysql_escape_string(). Однако, логика, да и практика, подсказывает, что достаточно удалить из текста одинарные кавычки (escape_string собственно их и экранирует), ибо это единственное, что может испортить запрос.
