Предотвращение внедрения JavaScript в веб-приложение PHP
Какие меры необходимы для предотвращения или предотвращения внедрения JavaScript-кода в веб-приложении PHP, чтобы не выдавалась конфиденциальная информация (лучшие практики в PHP, HTML/XHTML и JavaScript)?
5 ответов
Хорошим первым шагом является применение методов, перечисленных в вопросе, связанном с Гертом Г. Это подробно описывает множество функций, которые могут использоваться в различных ситуациях для очистки ввода, в том числе mysql_real_escape_string
, htmlentities()
, htmlspecialchars()
, strip_tags()
а также addslashes()
Лучший способ, по возможности, избегать вставки пользовательского ввода непосредственно в вашу базу данных. Используйте проверку ввода белого списка: в любой ситуации, когда у вас есть только ограниченный диапазон опций, выбирайте жестко запрограммированные значения для вставки, а не извлекайте ввод из любой обращенной к клиенту формы. По сути, это означает наличие только определенных значений, которые вы принимаете, вместо того, чтобы пытаться устранить / противостоять злым / неправильно сформированным / злонамеренным данным.
Например: если у вас есть форма с раскрывающимся списком для элементов, не используйте входные данные из этого раскрывающегося списка для вставки. Помните, что злонамеренный клиент может редактировать информацию, отправленную с отправкой формы, даже если вы думаете, что у него только ограниченные возможности. Вместо этого сделайте так, чтобы раскрывающийся список ссылался на индекс в массиве в вашем коде на стороне сервера. Затем используйте этот массив, чтобы выбрать, что вставить. Таким образом, даже если злоумышленник попытается отправить вам вредоносный код, он никогда не попадет в вашу базу данных.
Очевидно, что это не работает для приложений свободной формы, таких как форумы или блоги. Для тех, вы должны прибегнуть к методам "первого шага". Тем не менее, существует широкий спектр опций, которые можно улучшить с помощью проверки ввода в белый список.
Вы также можете использовать параметризованные запросы (или подготовленные операторы с переменными связывания) для ваших SQL-взаимодействий, где это возможно. Это сообщит серверу базы данных, что весь ввод данных является просто значением, поэтому он устраняет множество потенциальных проблем от атак с использованием инъекций. Во многих ситуациях это может охватывать даже приложения свободной формы.
Обработайте любое значение, которое вы выводите в html, с помощью htmlspecialchars() по умолчанию.
Единственное оправдание для того, чтобы не использовать htmlspecialchars(), - это когда вам нужно вывести в html строку, которая сама содержит html. В этом случае вы должны быть уверены, что эта строка из полностью безопасного источника. Если у вас нет такой уверенности, то вы должны пропустить его через html-фильтр белого списка, который допускает только тщательно ограниченный набор тегов, атрибутов и значений атрибутов. Вы должны быть особенно осторожны со значениями атрибутов. Вы никогда не должны позволять, чтобы все передавалось как значение атрибута, особенно для таких атрибутов, как src, hef, style.
Вы должны знать все места в вашем веб-приложении, где вы выводите что-либо в html без использования htmspeciachars (), убедитесь, что вам действительно нужны эти места, и помните, что, несмотря на всю вашу уверенность, эти места являются потенциальными уязвимостями.
Если вы думаете, что это слишком большая осторожность: "Зачем мне htmlspecialchar () эта переменная, которая, я знаю, содержит только целое число и теряет все драгоценные циклы ЦП?"
Помните это: вы не знаете, вы только думаете, что знаете, циклы процессора - самая дешевая вещь в мире, и почти все они будут потрачены впустую из-за ожидания доступа к базе данных или файловой системе или даже к памяти.
Также никогда не используйте черный список HTML-фильтров. Youtube сделал эту ошибку, и кто-то вдруг узнал, что только первым <script>
удаляется, и если вы введете второй комментарий, вы можете добавить любой Javascript в браузер посетителей.
Точно так же, чтобы избежать SQL-инъекций, обработайте с помощью mysql_real_escape_string() все значения, которые вы склеиваете с SQL-запросом, или, что еще лучше, используйте подготовленные операторы PDO.
Если вы не передаете ничего, что должно быть отформатировано как html, используйте:
strip_tags() <- Eliminates any suspicious html
а затем выполните следующую команду для очистки перед сохранением в БД
mysql_real_escape_string()
Если ваш ajax сохраняет введенный пользователем html через текстовое поле или wysiwyg, тогда изучите использование HTMLPurifier для удаления javascript, но разрешите использование html-тегов.
Я не полностью согласен с другими ответами, поэтому буду публиковать свои рекомендации.
Рекомендуемое чтение https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet
Внедрение Html: всякий раз, когда отображается какой-либо пользовательский контент, он должен быть соответствующим образом очищен с помощью htmlspecialchars или htmlentities при указании ENT_QUOTES, если он используется внутри одинарных кавычек. Я бы рекомендовал никогда не заключать в одинарные кавычки и всегда заключать в атрибуты двойные кавычки (не опускайте их). Это относится к таким вещам, как:
<input value="<?php echo htmlspecialchars($var); ?>" />
<textarea><?php echo htmlspecialchars($var); ?></textarea>
<p><?php echo htmlspecialchars($var); ?></p>
<img width="<?php echo htmlspecialchars($var); ?>" />
Инъекция Javascript: Лучшая практика (но не всегда практичная) никогда не заключать пользовательский контент в события и javascript. Тем не менее, если вы делаете, есть некоторые вещи, которые можно сделать, чтобы уменьшить риск. Только передать целочисленные идентификаторы. Если вам требуется что-то вроде спецификатора типа, то перед выходом используйте белый список и / или условную проверку. Возможно принудительное использование пользовательского контента в буквенно-цифровом формате только при необходимости; preg_replace("/[^A-Za-z0-9]/", '', $string);
но будьте очень осторожны с тем, что вы разрешаете здесь. Включайте контент только тогда, когда он заключен в кавычки, и обратите внимание, что htmlspecialchars / htmlentities вас здесь не защищает. Он будет интерпретироваться во время выполнения, даже если он был переведен в HTML-сущности. Это относится к таким вещам, как:
<a href="www.stackoverlow.com/?id=<?php echo (int)$id; ?>">Click</a>
href, src, style, onClick, etc.
Не вставляйте какой-либо пользовательский контент в другие области, такие как тело тегов сценария и т. Д., Если только он не переведен в int или какой-либо другой очень ограниченный набор символов (если вы знаете, что делаете).
SQL-инъекция: используйте подготовленные операторы, привязывайте к ним пользовательский контент и никогда не вставляйте пользовательский контент напрямую в запрос. Я бы порекомендовал создать класс для подготовленных операторов с помощью вспомогательных функций для ваших различных базовых типов операторов (и, находясь в этой теме, функционализировать все ваши операторы базы данных). Если вы решите не использовать подготовленные операторы, используйте mysql_real_escape_string() или аналогичные (не addlashes()). Проверяйте содержимое, когда это возможно, перед сохранением в базе данных, таким как форсирование / проверка целочисленных типов данных, условные проверки типов и т. Д. Используйте надлежащие типы и длины столбцов базы данных. Помните, что основной целью здесь является предотвращение внедрения SQL-кода, но вы также можете сделать защиту HTML-кода / JavaScript-кода здесь.
Другие ресурсы Я провел некоторые исследования в Интернете в надежде найти простое решение, уже общедоступное. Я нашел OWASP ESAPI, но он выглядит довольно устаревшим. Ссылки на версию php не работают в нескольких местах. Я думаю, что нашел это здесь; ESAPI PHP, но опять же он довольно устарел и не так прост, как я надеялся. Вы можете найти это полезным, однако.
В общем, никогда не думайте, что вы защищены, например, используете htmlentities в атрибуте onClick. Вы должны использовать правильный инструмент в правильном месте и избегать действий в неправильном месте.
На этот вопрос уже есть некоторые ответы, принятые и оцененные пользователями.
Вместо этого я также отправляю ответ, надеюсь, это будет работать нормально.
Это проверено мной.
$value = preg_replace("/[\'\")(;|`,<>]/", "", $value);
Функция preg_replace() прекрасно работает здесь.