$sql = 'INSERT INTO `sell`.`themes` (`name`, `preview`, `them`, `price`, `create_at`) VALUES (?, ?, ?, ?, NOW())';
$pdo->prepare($sql)
->execute(array($n['name'], $n['preview'], $n['them'], $n['price']));
Вот таким кодом вставляю в базу новые записи, когда в значениях любой из переменной есть кавычки они без экранирования вставляются в базу, это нормально?
вот скрин из PMA
Вы, видимо, не до конца понимаете, где и зачем нужно экранирование. Давайте разберём весь путь ваших данных от INSERT до вывода на экран в вашем браузере.
Отправка SQL-запроса
База данных должна уметь хранить произвольные данные, в том числе любые символы в любых строках. Но вот незадача — кавычки это спецсимволы в SQL. Если мы, возьмём, например, такую строку:
хорошие данные"), ("я хакер азаза"); --
и попытаемся её добавить через примерно такой запрос:
INSERT INTO mytable ("сюда подставляем строку")
то получится такой SQL-код:
INSERT INTO mytable ("хорошие данные"), ("я хакер азаза"); -- ")
Да, это SQL-инъекция. Вместо одной исходной строки база данных запишет две: хорошие данные
и я хакер азаза
.
Но ведь запрещать кавычки для предотвращения инъекции это неудобно, мы же наверно хотим сохранить строку хорошие данные"), ("я хакер азаза"); --
в базе данных как есть, чтобы пользователь её мог потом прочитать в точно таком же виде мог прочитать? (В конце концов, если бы все запрещали кавычки, я бы не смог написать этот ответ, в нём же много кавычек :)
К счастью, есть экранирование. Кавычки экранируются заменой "
на \"
(если в строке изначально есть обратный слэш \
, то он тоже экранируется заменой на \\
). С экранированием получается такой код:
INSERT INTO mytable ("хорошие данные\"), (\"я хакер азаза\"); -- ")
Так вот, PDO делает экранирование автоматически. Если всё сконфигурировано правильно, SQL-инъекция в коде из вашего вопроса невозможна.
Но это не значит, что экранированные кавычки так и сохранятся! Когда база данных парсит этот SQL-запрос, она, как бы корректнее выразиться, в общем автоматически убирает экранирование со строки. Экранирование нужно только для того, чтобы при разборе SQL-запроса база данных не попутала кавычку внутри строки с кавычкой, означающей окончание строки. После разбора база данных уже ничто ни с чем не попутает и всё экранирование можно безопасно убрать, и строка хорошие данные"), ("я хакер азаза"); --
в итоге сохраняется как есть. Здесь всё безопасно, база данных сама позаботится об этом, вам важно лишь экранировать строку перед подстановкой в SQL-запрос (повторюсь, PDO это делает автоматически, код из вопроса безопасен).
PMA забирает строку из базы данных
Перед отображением содержимого вам PMA делает запрос вроде SELECT * FROM mytable
и в ответе получает нашу строку со всеми кавычками, сохранёнными в предыдущем шаге (как устроен протокол передачи строки от базы данных в PMA, я не знаю, но там тоже всё безопасно). Потом PMA должен запихнуть эту строку в HTML-код с красивой табличкой и передать его вам, чтобы браузер эту табличку нарисовал.
Но здесь уже становится возможно XSS. Это когда в строке оказывается что-то вроде <script>alert("XSS!")</script>
— если запихнуть это в HTML-код как есть, то браузер это воспримет не как текст, а как HTML-тег, обозначающий скрипт, и выполнит любой код внутри него (а этот любой код сможет, например, передать злоумышленнику ваши логин и пароль от текущего сайта). Поэтому перед выводом PMA тоже всё экранирует с помощью HTML-сущностей.
Из строки
хорошие данные"), ("я хакер азаза"); --
получается
хорошие данные"), ("я хакер азаза"); --
а из строки
<script>alert("XSS!")</script>
получается
<script>alert("XSS!")</script>
Если в исходной строке есть символ &
, то он экранируется как &
. Если там уже есть &
, то с экранированием получается &amp;
ну и так далее :)
Чтение HTML-кода браузером
Сервер (PMA) отвечает браузеру HTML-кодом, в котором все спецсимволы в ваших строках вот так вот экранированы. Когда браузер читает это всё, он теперь воспринимает это не как теги, а как обычный текст, и опасности появления XSS нет. Но перед выводом на экран тоже убирает всё экранирование — заменяет "
обратно на "
и так далее.
Поэтому вы в итоге видите не fhfh\" OR 1
и не fhfh\" OR 1
, а fhfh" OR 1
— ровно такую строку, какую вы изначально и хотели отправить в базу данных.
$sql = "INSERT INTO 'sell'.'themes' ('name', 'preview', 'them', 'price', 'create_at') VALUES (?, ?, ?, ?, NOW())";
$pdo->prepare($sql) ->execute(array($n['name'], $n['preview'], $n['them'], $n['price']));
Категорически НЕЛЬЗЯ без ручного екранирования вставлять так кавычки, только так.
$foo = "fuiyg 'ookjgi' lifuo";
- так можно
$foo = 'fjokt "hkooy" ogupy "jkjf" gju';
и так можно
$foo = 'lkgoo 'dgoov' kifg 'fik' jgu';
- так, и
$foo = "fynnfr "fgjiy" dhj "fhji" dgj";
- нельзя
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Всем привет, не понимаю как правильно сделать фильтр товаров по свойствамУ меня yii2 advanced! В фильтре хочу вывести хотя бы примитивное что бы понять...