Уже давно меня мучает вопрос: Как защитить свой сайт от SQL-Injection. В былые времена я использовал mysql_real string_escape
для экранирования кавычек. Но прошло некое время, и я узнал про PDO
, говорится, мол, эта тема неплохо поможет в защите сайта. Скажем, я не великий хакер и никак это не могу проверить, я знаю, что при mysql_real string_escape
все кавычки и прочая ерунда экранировались - и вуаля, вы уже в домике.
Сейчас я работаю над своим проектом и решил проверить сайт на защиту проникновения. В результате, что я делал:
Я просто брал и вводил данные с кавычками, например, Infor`mat'ion. Как я уже говорил, я не великий хакер, но точно знаю, что вся эта дрянь должна экранироваться, но она так и заносилась в базу данных, что натолкнуло меня на мысль, что никакой защиты у меня, по сути, и нету. А данные я заносил вот таким вот образом:
$sql = "INSERT INTO chat (time, login, private, text) values(?, ?, ?, ?)";
$db->prepare($sql)->execute(array($time, $login, $private, $text));`
Этот метод я вычитал на хабре в "Почему стоит пользоваться PDO для работы с базой данных", подключение такое же, как и указано в статье.
Как можно защититься от этих инъекций?
При использовании подготовленных выражений (prepared statement) параметры внешнего происхождения отправляются на сервер отдельно от самого запроса либо автоматически экранируются клиентской библиотекой.
Создаём таблицу drop_table
. Далее
$name = "Evil'); DROP TABLE drop_table;--";
$sql = "INSERT INTO `test` (`name`) values('{$name}');";
$statement = $db->prepare($sql);
$statement->execute();
Таблица drop_table
успешно удалена. :)
Теперь тот же запрос, но только через prepared statement:
$sql = "INSERT INTO `test` (`name`) values(?);";
$statement = $db->prepare($sql);
$statement->execute([$name]);
В таблицу test
добавилась запись Evil'); DROP TABLE drop_table;--
Таким образом, мы обезопасили себя от SQL injection, но не защитили от XSS.
В последнем случае требуется:
(int)$age
. В PHP существует набор фильтров, созданных именно для таких случаев;Если по каким-то причинам требуется хранить в базе html от источника, который не вызывает доверие, то можно воспользоваться HTML Purifier.
Немного рекламы: :)
Все правильно: в таблицу и должна добавляться строка «Infor`mat'ion». Экранирование должно происходить именно в момент запроса, а не храниться в таком виде. И PDO прекрасно с этим справляется. И mysql_real_escape_string
(и mysqli_real_escape_string
) — тоже. И даже str_replace
— это тоже способ защититься. (См. UPD) То новое, что нам дает PDO, так это слежение за типами передаваемых данных и разграничение действия и данных. Популярная ошибка, которая приводила к плачевным результатам заключалась в том, что некоторые забывали проверять нестроковые типы:
$q = "SELECT * FROM `table` WHERE `id` = ".$_GET['post_id'];
Разница налицо:
$q = "SELECT * FROM `table` WHERE `id` = ".intval($_GET['post_id']);
Или просто всегда обрабатывай входные данные, следи за кавычками, за возможными представлениями чисел, за представлениями bool
-данных... Или просто положись на готовую обертку, к примеру, PDO. :)
UPD: WARNING!
mysqli_real_escape_string
(вероятно), mysql_real_escape_string
, а тем более str_replace
— небезопасны (\xbf\x27 и другие проблемы), используйте MySQL только в режиме настоящих подготовленных запросов! PDO нужно правильно использовать (спасибо @romeo за ссылку).
PDO, и его prepare.
$temp = $mysql->prepare('DELETE FROM `unigies` WHERE `idUser` = :idUser Limit 1;');
$temp->bindParam(':idUser', $id, PDO::PARAM_INT);
$temp->execute();
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Есть веб-интерфейс, куда юзер загружает файл и файл процесситсяНужно чтобы после загрузки началась обработка файла и пользователь в реальном...
Проблема в том что у меня в базе данных есть значение одного столбца, оно обычно false, но бывает случается что пустое, как мне при выводе объединить...
Я создал следующие меню на bootstrap и перенёс его в Wordpress, но оно почему то оно не работает? Помогите исправить
$this->name — свойство, но что дальше? Те