Что такое SQL-инъекция и как ее предотвратить в PHP-приложениях?

Таким образом, вы думаете, что ваша база данных SQL является производительной и защищена от мгновенного уничтожения? Ну, SQL-инъекция не согласна!


Да, речь идет о мгновенном уничтожении, потому что я не хочу открывать эту статью с обычной неубедительной терминологией «усиление безопасности» и «предотвращение злонамеренного доступа». SQL-инъекция – такая старая уловка в книге, что каждый, каждый разработчик, знает об этом очень хорошо и хорошо знает, как предотвратить это. За исключением того странного времени, когда они ускользают, и результаты могут быть не чем иным, как катастрофическим.

Если вы уже знаете, что такое SQL-инъекция, смело переходите ко второй половине статьи. Но для тех, кто только начинает заниматься веб-разработкой и мечтает взять на себя более высокие должности, необходимо некоторое введение..

Что такое SQL-инъекция?

Ключ к пониманию SQL-инъекций находится в его названии: SQL + Injection. Слово «инъекция» здесь не имеет никакого медицинского значения, а скорее употребление глагола «ввести». Вместе эти два слова передают идею внедрения SQL в веб-приложение..

Ввод SQL в веб-приложение. , , ммм , , Разве это не то, что мы делаем в любом случае? Да, но мы не хотим, чтобы злоумышленник управлял нашей базой данных. Давайте разберемся с помощью примера.

Допустим, вы создаете типичный веб-сайт PHP для местного магазина электронной коммерции, поэтому вы решили добавить контактную форму, например:

Ваше имя

Твое сообщение

И давайте предположим, что файл send_message.php хранит все в базе данных, чтобы владельцы магазина могли позже читать пользовательские сообщения. Может иметь такой код:

<?PHP

$ name = $ _POST [‘name’];
$ message = $ _POST [‘message’];

// проверяем, есть ли у этого пользователя сообщение
mysqli_query ($ сопп, "SELECT * из сообщений, где name = $ name");

// Другой код здесь

Итак, вы сначала пытаетесь увидеть, есть ли у этого пользователя непрочитанное сообщение. Запрос SELECT * из сообщений, где name = $ name, кажется достаточно простым, верно?

НЕПРАВИЛЬНО!

В нашей невиновности мы открыли двери для мгновенного уничтожения нашей базы данных. Для этого злоумышленнику необходимо выполнить следующие условия:

  • Приложение работает на базе данных SQL (сегодня почти каждое приложение работает)
  • Текущее подключение к базе данных имеет разрешения «редактировать» и «удалять» в базе данных.
  • Названия важных таблиц можно угадать

Третий момент означает, что теперь, когда злоумышленник знает, что вы управляете магазином электронной коммерции, вы, скорее всего, сохраните данные заказа в таблице заказов. Вооружившись всем этим, все, что нужно сделать злоумышленнику, это указать его имя:

Джо; усекать заказы;? Да сэр! Давайте посмотрим, каким будет запрос, когда он будет выполнен скриптом PHP:

SELECT * FROM сообщения ГДЕ имя = Джо; урезать заказы;

Хорошо, в первой части запроса есть синтаксическая ошибка (без кавычек вокруг «Джо»), но точка с запятой вынуждает движок MySQL начать интерпретацию нового: усеченных ордеров. Просто так, одним махом, вся история заказов исчезла!

Теперь, когда вы знаете, как работает SQL-инъекция, пришло время посмотреть, как это остановить. Для успешного внедрения SQL необходимо выполнить два условия:

  1. Скрипт PHP должен иметь права на изменение / удаление базы данных. Я думаю, что это верно для всех приложений, и вы не сможете сделать ваши приложения доступными только для чтения. Guess И угадайте, что, даже если мы удалим все привилегии на изменение, SQL-инъекция все еще может позволить кому-то запускать запросы SELECT и просматривать всю базу данных, включая конфиденциальные данные. Другими словами, снижение уровня доступа к базе данных не работает, и ваше приложение все равно нуждается в этом.
  2. Пользовательский ввод обрабатывается. Единственный способ внедрения SQL-кода – это когда вы принимаете данные от пользователей. Еще раз, не практично останавливать все входные данные для вашего приложения только потому, что вы беспокоитесь о внедрении SQL.

Предотвращение внедрения SQL в PHP

Теперь, учитывая, что соединения с базой данных, запросы и пользовательский ввод являются частью жизни, как мы можем предотвратить внедрение SQL? К счастью, это довольно просто, и есть два способа сделать это: 1) очистить пользовательский ввод и 2) использовать подготовленные операторы.

Дезинфицировать пользовательский ввод

Если вы используете более старую версию PHP (5.5 или ниже, и это часто случается на виртуальном хостинге), было бы целесообразно выполнить весь пользовательский ввод с помощью функции mysql_real_escape_string (). В основном, что он делает, он удаляет все специальные символы в строке, чтобы они теряли свое значение при использовании базой данных.

Например, если у вас есть строка, похожая на строку «Я», злоумышленник может использовать символ одинарной кавычки (‘) для манипулирования создаваемым запросом к базе данных и вызвать внедрение SQL. Запуск его через mysql_real_escape_string () приводит к появлению строки, которая добавляет обратную косую черту к одиночной кавычке, избегая ее. В результате вся строка теперь передается в базу данных как безвредная строка вместо возможности участвовать в манипулировании запросами..

У этого подхода есть один недостаток: это действительно очень старая техника, которая согласуется со старыми формами доступа к базе данных в PHP. Начиная с PHP 7, этой функции больше не существует, что приводит нас к следующему решению..

Используйте готовые заявления

Подготовленные операторы – это способ сделать запросы к базе данных более безопасными и надежными. Идея состоит в том, что вместо отправки необработанного запроса в базу данных, мы сначала сообщаем базе данных структуру запроса, который мы будем отправлять. Это то, что мы подразумеваем под «подготовкой» заявления. Как только инструкция подготовлена, мы передаем информацию как параметризованные входные данные, чтобы база данных могла «заполнить пробелы», подключив входные данные к структуре запроса, которую мы отправили ранее. Это отнимает любую особую мощность, которую могут иметь входные данные, заставляя их рассматриваться как простые переменные (или полезные нагрузки, если хотите) во всем процессе. Вот как выглядят подготовленные заявления:

<?PHP
$ servername = "локальный";
$ username = "имя пользователя";
$ пароль = "пароль";
$ dbname = "MyDB";

// Создать соединение
$ conn = new mysqli ($ имя_сервера, $ имя пользователя, $ пароль, $ dbname);

// Проверьте подключение
if ($ conn->connect_error) {
умереть("Ошибка подключения: " . $ сопп->connect_error);
}

// подготовить и связать
$ stmt = $ conn->подготовить("INSERT INTO MyGhest (имя, фамилия, адрес электронной почты) ЗНАЧЕНИЯ (?,?,?)");
$ STMT->bind_param ("SSS", $ имя, $ фамилия, $ email);

// установить параметры и выполнить
$ firstname = "Джон";
$ фамилия = "лань";
$ email = "[Электронная почта защищена]";
$ STMT->выполнить ();

$ firstname = "Мэри";
$ фамилия = "Моу";
$ email = "[Электронная почта защищена]";
$ STMT->выполнить ();

$ firstname = "Julie";
$ фамилия = "Дули";
$ email = "[Электронная почта защищена]";
$ STMT->выполнить ();

эхо "Новые записи успешно созданы";

$ STMT->близко();
$ сопп->близко();
?>

Я знаю, что этот процесс кажется излишне сложным, если вы новичок в подготовленных заявлениях, но концепция стоит потраченных усилий. Вот хорошее введение в это.

Для тех, кто уже знаком с расширением PDO в PHP и использует его для создания готовых операторов, у меня есть небольшой совет.

Предупреждение: будьте осторожны при настройке PDO

Используя PDO для доступа к базе данных, мы можем впасть в ложное чувство безопасности. «Ах, хорошо, я использую PDO. Теперь мне не нужно думать ни о чем другом », – таково наше мышление. Это правда, что PDO (или подготовленные MySQLi операторы) достаточно для предотвращения всевозможных SQL-атак, но вы должны быть осторожны при его настройке. Обычно просто скопируйте и вставьте код из учебников или из ваших предыдущих проектов и двигайтесь дальше, но этот параметр может отменить все:

$ DBConnection->setAttribute (PDO :: ATTR_EMULATE_PREPARES, true);

Этот параметр говорит PDO эмулировать подготовленные операторы, а не фактически использовать функцию подготовленных операторов базы данных. Следовательно, PHP отправляет простые строки запроса в базу данных, даже если ваш код выглядит так, как будто он создает подготовленные операторы, устанавливает параметры и все такое. Другими словами, вы так же уязвимы для внедрения SQL, как и раньше. ��

Решение простое: убедитесь, что для этой эмуляции установлено значение false.

$ DBConnection->setAttribute (PDO :: ATTR_EMULATE_PREPARES, false);

Теперь PHP-скрипт вынужден использовать подготовленные операторы на уровне базы данных, предотвращая все виды SQL-инъекций..

Предотвращение использования WAF

Знаете ли вы, что вы также можете защитить веб-приложения от внедрения SQL с помощью WAF (брандмауэр веб-приложений)?

Ну, не только SQL-инъекция, но и многие другие уязвимости уровня 7, такие как межсайтовый скриптинг, неработающая аутентификация, межсайтовая подделка, раскрытие данных и т. Д. Вы можете использовать самодостаточный хостинг, такой как Mod Security или облачный, как показано ниже..

SQL-инъекция и современные PHP-фреймворки

Внедрение SQL настолько распространено, так просто, так расстраивает и так опасно, что все современные веб-фреймворки PHP встроены в контрмеры. В WordPress, например, у нас есть $ wpdb->Функция prepare (), тогда как если вы используете инфраструктуру MVC, она сделает всю грязную работу за вас, и вам даже не придется думать о предотвращении внедрения SQL. Немного раздражает, что в WordPress вам приходится явно готовить операторы, но, эй, речь идет о WordPress. ��

В любом случае, я хочу сказать, что современные разработчики веб-сайтов не должны думать о внедрении SQL-кода, и в результате они даже не подозревают о такой возможности. Таким образом, даже если они оставляют один бэкдор открытым в своем приложении (может быть, это параметр запроса $ _GET и старые привычки запуска грязного запроса), результаты могут быть катастрофическими. Так что всегда лучше потратить время, чтобы глубже погрузиться в фундамент.

Вывод

SQL-инъекция – очень неприятная атака на веб-приложение, но ее легко избежать. Как мы видели в этой статье, осторожность при обработке пользовательского ввода (кстати, SQL-инъекция – не единственная угроза, которую приносит обработка пользовательского ввода) и запрос базы данных – это все, что нужно сделать. Тем не менее, мы не всегда работаем над безопасностью веб-фреймворка, поэтому лучше знать об этом типе атаки и не поддаваться ей..

Jeffrey Wilson Administrator
Sorry! The Author has not filled his profile.
follow me
    Like this post? Please share to your friends:
    Adblock
    detector
    map