Предотвращение JavaScript-инъекций в веб-приложении PHP

Каковы меры, необходимые для предотвращения или прекращения инъекций JavaScript в веб-приложении PHP, чтобы конфиденциальная информация не выдавалась (лучшие практики в PHP, HTML / XHTML и JavaScript)?

Хорошим первым шагом является применение методов, перечисленных в вопросе Gert G, связанных . Это подробно описывает множество функций, которые можно использовать в разных ситуациях для очистки ввода, включая mysql_real_escape_string , htmlentities() , htmlspecialchars() , strip_tags() и addslashes()

Лучше всего, когда это возможно, избегать ввода пользовательского ввода непосредственно в вашу базу данных. Использовать проверку входных данных в белый список : в любой ситуации, когда у вас есть только ограниченный диапазон опций, выберите из жестко заданных значений для вставки, вместо того, чтобы вводить данные из любой стороны, обращенной к стороне клиента. В принципе, это означает наличие только определенных значений, которые вы принимаете, вместо того, чтобы пытаться устранить / противодействовать злобному / неправильному образу / вредоносному вводу.

Например: если у вас есть форма с выпадающим списком для элементов, не используйте ввод из этого раскрывающегося списка для вставки. Помните, что вредоносный клиент может редактировать информацию, отправленную с помощью формы, даже если вы считаете, что у них ограниченные возможности. Вместо этого, выпадающий список ссылается на индекс в массиве в вашем серверном коде. Затем используйте этот массив, чтобы выбрать, что нужно вставить. Таким образом, даже если злоумышленник пытается отправить вам вредоносный код, он никогда не попадает в вашу базу данных.

Очевидно, что это не работает для приложений свободной формы, таких как форумы или блоги. Для этих целей вам придется отказаться от техники «первого шага». Тем не менее, существует широкий спектр опций, которые можно улучшить с помощью проверки входных данных в белый список.

Вы также можете использовать параметризованные запросы (например, подготовленные операторы с переменными привязки) для своих взаимодействий sql, где это возможно. Это скажет серверу базы данных, что все входные данные являются просто значением, поэтому он смягчает множество потенциальных проблем от инъекционных атак. Во многих ситуациях это может даже охватывать приложения свободной формы.

Относитесь к любому значению, которое вы выводите в html с помощью htmlspecialchars () по умолчанию .

Только извинение за не использование htmlspecialchars () – это когда вам нужно выводить на строку html, которая сама содержит html. В этом случае вы должны быть уверены, что эта строка из полностью безопасного источника. Если у вас нет такой уверенности, вы должны передать его через whitelist html filter, который позволяет использовать только ограниченный набор тегов, атрибутов и значений атрибутов. Вы должны особенно внимательно относиться к значениям атрибутов. Вы никогда не должны допускать, чтобы все передавалось как значение атрибута, особенно для таких атрибутов, как src, hef, style.

Вы должны знать все места в своем webapp, где вы выводите что-либо в html без использования htmspeciachars (), убедитесь, что вам действительно нужны эти места, и имейте в виду, что, несмотря на всю вашу уверенность, эти места являются потенциальными уязвимостями.

Если вы думаете, что это слишком осторожно: «Зачем мне нужна htmlspecialchar () эта переменная, которую я знаю, она содержит только целое число и освобождает все драгоценные циклы процессора?»

Помните об этом: вы не знаете, вы только думаете, что знаете, циклы процессоров – самая дешевая вещь в мире, и почти все они будут потрачены впустую, ожидая базы данных или файловой системы или даже доступа к памяти.

Также никогда не используйте фильтры черного списка html. Youtube совершил эту ошибку, и кто-то вдруг обнаружил, что только первый <script> удален, и если вы введете второй в комментарий, вы можете ввести любой Javascript в браузер посетителей.

Аналогично, чтобы избежать SQL-инъекций, обработайте с помощью mysql_real_escape_string () все значения, которые вы приклеиваете к SQL-запросу, или еще лучше используете инструкции PDO Prepared.

Если вы не передаете что-то, что должно быть сформировано как html, используйте:

 strip_tags() <- Eliminates any suspicious html 

а затем запустите следующее, чтобы очистить до сохранения в db

 mysql_real_escape_string() 

Если ваш ajax сохраняет введенный пользователем html через текстовое поле или wysiwyg, посмотрите на использование HTMLPurifier, чтобы вырезать javascript, но разрешить теги html.

Я не согласен полностью с другими ответами, поэтому я опубликую свои рекомендации.

Рекомендуемое чтение XSS_ (Cross_Site_Scripting) _Prevention_Cheat_Sheet

Html Injection: всякий раз, когда вы показываете любой контент, представленный пользователем, он должен быть надлежащим образом очищен с помощью 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 Injection: Лучшая практика (но не всегда практичная) никогда не эхо-пользовательский контент в события и javascript. Однако, если вы это сделаете, есть некоторые вещи, которые можно сделать для снижения риска. Только передать целочисленные id. Если вам требуется что-то вроде спецификатора типа, то перед выдачей используйте белый список и / или условную проверку. Возможно, принудительное включение пользовательского контента в буквенно-цифровой формат только тогда, когда это необходимо; 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 Injection: использовать подготовленные операторы , связывать с ними пользовательский контент и никогда напрямую не вставлять содержимое пользователя в запрос. Я бы рекомендовал создать класс для подготовленных операторов с вспомогательными функциями для разных базовых типов инструкций (и, в то время как по теме, функционализировать все ваши заявления базы данных). Если вы решите не использовать подготовленные инструкции, используйте mysql_real_escape_string () или аналогичные (not addslashes ()). Проверять содержимое по возможности перед сохранением в базе данных, например, форсировать / проверять тип целочисленных данных, условные проверки типов и т. Д. Использовать соответствующие типы столбцов базы данных и длины. Помните, что главная цель здесь – предотвратить внедрение sql, но здесь вы также можете сделать защиту от html / javascript.

Другие ресурсы Я провел некоторое исследование в Интернете в надежде найти простое решение, уже общедоступное. Я нашел OWASP ESAPI, но, похоже, довольно устарел. Ссылки на версию php разбиты на несколько мест. Кажется, я нашел его здесь; ESAPI PHP, но опять же он довольно устарел и не так прост, как я надеялся. Однако вы можете найти это полезным.

В общем, никогда не предполагайте, что вы защищены, например, используя htmlentities в атрибуте onClick. Вы должны использовать правильный инструмент в нужном месте и избегать действий в неправильном месте.