Целый день читал статьи про XSS, инъекции, htmlspecialchars, addslashes… И, в конце концов, запутался окончательно. Задача стоит такая: на странице 1.phpпосетитель вводит данные в форму (без перезагрузки, с подсчетом количества введенных знаков), и эти данные записываются в базу. При следующем посещении страницы посетитель видит в форме ранее введенную им информацию и может её изменить. Кроме того, полученная от пользователя информация подвергается логической обработке – дезактивируются ссылки и вставляются шорт-коды. Возможно, будет делаться что-то ещё – этот этап пока в разработке. И эта инфа видна на странице 2.php. Чтобы разобраться, как это работает, я сделал макет, в котором вместо базы инфа записывается в текстовые файлы. Вот их коды: Файл 1.php: HTML: <script src="/js/jquery-3.6.4.min.js"></script> <!-- Подсчет оставшихся знаков --> <script> function checklength(t){ var ml = $(t).attr('maxlength'); var diff = ml - $(t).val().length; var ad = $(t).nextAll('div:first'); if (diff==ml){ ad.html(' ').css('color','green'); } else if(diff>10){ ad.text('Осталось знаков: '+diff).css('color','green'); } else{ ad.text('Осталось знаков: '+diff+'!').css('color','red'); } } </script> <?php $busedu = @file_get_contents('storage.txt'); // Замена сущностей на HTML $busedu = html_entity_decode($busedu, ENT_QUOTES, 'UTF-8') ?> <div id="busedu"> <textarea name="busedu" maxlength="500" onkeyup="checklength(this);" ><?php echo $busedu; ?></textarea> <div class="znak"> </div> <div class="maxznak"><p style="text-align:center; margin: 0;">Max 500</p></div> </div> <input type="hidden" name="id-form" value="busedu-f"> <input class="pusk" style="display:block;" type="submit" name="submit" value="Отправить"> </form> <div id="busedu-fs"></div> <script> $(document).ready(function () { $('.group_b').submit(function () { // Получение ID формы var formID = $(this).attr('id'); // Добавление решётки к имени ID var formNm = $('#' + formID); var formNms = $('#' + formID + 's'); $.ajax({ type: "POST", url: '/send.php', data: formNm.serialize(), beforeSend: function () { // Вывод текста в процессе отправки $(formNms).html('<p style="text-align:center">Отправка...</p>'); }, success: function (data) { // Вывод текста результата отправки $(formNms).html('<p style="text-align:center">'+data+'</p>'); }, error: function (jqXHR, text, error) { // Вывод текста ошибки отправки $(formNms).html(error); } }); return false; }); }); </script> Файл send.php PHP: if ($_POST['id-form'] == "busedu-f") { // Замена HTML сущностями $busedu = htmlentities($_POST['busedu'], ENT_QUOTES, 'UTF-8'); if (strlen($busedu) > 0) { file_put_contents('storage.txt', $busedu); echo "Принято"; } else { file_put_contents('storage.txt', ""); echo "Данные не введены или удалены"; } /* Здесь какая-то обработка на уровне РНР, включая регулярку, в результате которой удаляются ссылки и вставляются шорт-коды, и из переменной $busedu формируется переменная $control */ file_put_contents(control.txt', $control); } Файл 2.php PHP: $control = @file_get_contents(control.txt'); echo $control; Здесь вместо базы используется запись в файлы, в реальном коде будет запись в базу. Тем не менее, как мне кажется, экранировать (использовать addslashes) нет нужды, поскольку кавычки заменены их сущностями. Правильно ли здесь сделана защита от хакеров? Или надо сделать что-то иначе?
Лишним не будет. Только нужно использовать спец. функцию экранирования БД-шной либы (addslashes используют, когда др. вариантов нет). А вообще вставку «больших данных» выполняют подготовленным запросом. Там экранирование не используется.
Вот такой тезис я понять не могу. Я делаю сайт и мне нужно, чтобы им могли пользоваться, и при этом сайт сохранял свою работоспособность. То есть, чтобы хакеры не имели возможности вывести его из строя или украсть персональные данные зарегистрированных лиц. Как мне кажется, такая задача стоит перед любым разработчиком. Почему для Вас это «сферический конь в вакууме»? Не могли бы Вы пояснить Вашу мысль или сформулировать её иначе? Какая ещё может быть задача?
Уважаемый miketomlin хочет сказать, что универсального решения нет, и, в зависимости от того как вы используете в своем сценарии пользовательский ввод, придется использовать решение специализированное. Как то: Форматирование, экранирование или подготовленные запросы при доступе к базам данных, Преобразование сущностей при выводе на экран. И т.д.
Так я же написал, как будет использоваться результат ввода. Специально всё подробно описал. Что еще тут нужно добавить?
Сформулируйте вопрос по-другому. Что-то вроде "получаю строку из формы и использую её для составления запроса к базе вот так... Безопасно ли это?"
No. Если речь об обычном тексте, он фильтруется и т.п. при вводе или выводе, потом кодируется в HTML при вводе или выводе. После кодирования при выводе не в форму могут добавляться br'ы/абзацы, обрабатываться шорткоды (если шорткоды не производят HTML-код, они могут обрабатываться и до кодирования) и т.п. С HTML-текстом (т.е. текстом, в котором должен сохраняться работающий HTML-код) все то же самое, только кодироваться он должен при выводе в форму, иначе нет.
@Vladd55 Общий подход должен быть пессимистическим: запрещено всё, что не разрешено. 1. При записи использовать подготовленные запросы. 2. При выводе экранировать все html сущности. Это безопасно. Теперь предположим, что ты хочешь разрешить некоторые теги или использовать разметку markdown или bbcode — заменяешь пункт 2 на транслятор с нужного языка разметки. Лучше воспользоваться готовым проверенным компонентом, чем писать свой и накосячить.
При сохранении инфы в базу, она не меняется. Чтобы не было sql иньекции надо использовать mysqli_real_escape_string или подготовленные запросы pdo При выводе пропускаешь просто через htmlspecialchars. Но так это будет чисто текст выводить. Если что то хочешь дополнительное, то можно предложить пользователю редактор где он будет например bb-кодами что то оформлять. Ты при выводе потом по ним изменишь. А если надо чтобы он пожирнее html набирал и выводил, то нужна библиотека HTML Purifier