Каковы наилучшие методы предотвращения XSS-атак на PHP-сайте
У меня PHP настроен так, что магические кавычки включены, а регистровые глобалы выключены.
Я делаю все возможное, чтобы всегда вызывать htmlentities() для всего, что я выдаю, что является производным от пользовательского ввода.
Я также иногда просматриваю свою базу данных для общих вещей, используемых в XSS, например...
<script
что еще я должен делать и как я могу убедиться, что вещи, которые я пытаюсь сделать всегда сделано.
20 ответов:
экранирование ввода-это не лучшее, что вы можете сделать для успешной профилактики XSS. Также выход должен быть экранирован. Если вы используете Smarty template engine, вы можете использовать
|escape:'htmlall'
модификатор для преобразования всех чувствительных символов в HTML-объекты (я использую собственный|e
модификатор, который является псевдонимом выше).мой подход к безопасности ввода / вывода:
- сохранить пользовательский ввод не изменен (нет HTML экранирования на входе, только DB-aware экранирование осуществляется через PDO подготовлен Ведомости)
- escape on output, в зависимости от того, какой формат вывода вы используете (например, HTML и JSON нужны разные правила экранирования)
Я придерживаюсь мнения, что не следует ничего избегать во время ввода, только на выходе. Поскольку (большую часть времени) вы не можете предположить, что знаете, куда идут эти данные. Например, если у вас есть форма, которая принимает данные, которые позже появляются в электронном письме, которое вы отправляете, вам нужно другое экранирование (в противном случае злоумышленник может переписать ваши заголовки электронной почты).
другими словами, вы можете убежать только в самый последний момент, когда данные "покидают" ваш применение:
- элемент списка
- запись в XML-файл, escape для XML
- запись в БД, escape (для этой конкретной СУБД)
- написать письмо, побег для электронной почты
- etc
короче говоря:
- вы не знаете, куда идут ваши данные
- данные могут фактически оказаться в более чем одном месте, нуждаясь в разных механизмах экранирования, но не в обоих
- данные экранированы неправильно цель действительно не хороша. (Например, получить электронное письмо с темой "перейти в бар Томми".)
Esp #3 произойдет, если вы экранируете данные на входном уровне (или вам нужно снова де-экранировать его и т. д.).
PS: Я поддержу совет не использовать magic_quotes, это чистое зло!
есть много способов сделать XSS (см. http://ha.ckers.org/xss.html) и это очень трудно поймать.
Я лично делегирую это в текущую структуру, которую я использую (например, Code Igniter). Хотя он и не идеален, он может поймать больше, чем когда-либо делали мои ручные процедуры.
Это большой вопрос.
во-первых, не экранируйте текст на входе, за исключением того, чтобы сделать его безопасным для хранения (например, помещать в базу данных). Причина этого заключается в том, что вы хотите сохранить то, что было введено, чтобы вы могли контекстуально представить его по-разному и в разных местах. Внесение изменений здесь может поставить под угрозу вашу последующую презентацию.
когда вы идете, чтобы представить ваши данные отфильтровать то, что не должно быть там. Например, если нет причины для поиска javascript за это и снимают его. Простой способ сделать это-использовать strip_tags функция и только представить HTML-теги, которые вы разрешаете.
Далее, возьмите то, что у вас есть, и передайте его мысли htmlentities или htmlspecialchars, чтобы изменить то, что есть для символов ascii. Сделайте это на основе контекста и того, что вы хотите получить.
Я бы также предложил отключить магические цитаты. Он был удален из PHP 6 и считается плохой практикой его использования. Подробности на сайте http://us3.php.net/magic_quotes
для более подробной информации проверьте http://ha.ckers.org/xss.html
Это не полный ответ, но, надеюсь, достаточно, чтобы помочь вам начать работу.
Рих пишет:
Я делаю все возможное, чтобы всегда вызывать htmlentities() для всего, что я выдаю, что является производным от пользовательского ввода.
см. эссе Джоэла о Делая Код Выглядеть Неправильно для помощи с этим
Я опираюсь на PHPTAL для этого.
В отличие от Smarty и простого PHP, он экранирует все выходные данные по умолчанию. Это большая победа для безопасности, потому что ваш сайт не станет vurnelable, если вы забудете
htmlspecialchars()
или|escape
куда-то.XSS-это специфичная для HTML атака, поэтому вывод HTML-это правильное место для ее предотвращения. Вы не должны пытаться предварительно фильтровать данные в базе данных, потому что вам может понадобиться выводить данные на другой носитель, который не принимает HTML, но имеет свой собственный риск.
библиотека шаблонов. или, по крайней мере, это то, что должны делать библиотеки шаблонов. Чтобы предотвратить XSS все выходной сигнал должен быть закодирован. Это не является задачей основной логики приложения / управления, она должна обрабатываться исключительно методами вывода.
Если вы посыпаете htmlentities () thorughout ваш код, общий дизайн неверен. И как вы предполагаете, вы можете пропустить одно или два места. Вот почему единственным решением является строгое кодирование html -> когда выходные vars записываются в поток html/xml.
к сожалению, большинство библиотек шаблонов php только добавляют свой собственный синтаксис шаблона, но не заботятся о выходной кодировке, локализации, проверке html или о чем-либо важном. Может быть, кто-то еще знает правильную библиотеку шаблонов для php?
экранирование всего пользовательского ввода достаточно для большинства сайтов. Также убедитесь, что идентификаторы сеанса не попадают в URL-адрес, поэтому их нельзя украсть из
Referer
ссылка на другой сайт. Кроме того, если вы разрешаете своим пользователям отправлять ссылки, убедитесь, что нетjavascript:
протокольные ссылки разрешены; они будут выполнять сценарий, как только пользователь нажимает на ссылку.
Если вы обеспокоены атаками XSS, кодирование выходных строк в HTML является решением. Если вы не забыли кодировать каждый выходной символ в формате HTML, нет никакого способа выполнить успешную атаку XSS.
подробнее: очистка пользовательских данных: как и где это сделать
лично я бы отключить magic_quotes. В PHP5+ он отключен по умолчанию, и лучше кодировать, как будто его вообще нет, поскольку он не избегает всего, и он будет удален из PHP6.
далее, в зависимости от того, какой тип пользовательских данных вы фильтруете будет диктовать, что делать дальше, например, если это просто текст, например, имя, то
strip_tags(trim(stripslashes()));
это или для проверки диапазонов используйте регулярные выражения.Если вы ожидаете определенный диапазон значений, создайте массив допустимые значения и только разрешить эти значения через (
in_array($userData, array(...))
).Если вы проверяете числа, используйте is_numeric для принудительного применения целых чисел или приведения к определенному типу, это должно предотвратить попытки людей отправлять строки вместо них.
Если у вас есть PHP5. 2+, то подумайте, глядя на filter () и использование этого расширения может фильтровать различные типы данных, включая адреса электронной почты. Документация не особенно хороша, но улучшается.
Если вы должны обрабатывать HTML, то вы должны рассмотреть что-то вроде PHP входной фильтр или в HTML-очиститель. Очиститель HTML также будет проверять HTML на соответствие. Я не уверен, что входной фильтр все еще разрабатывается. Оба позволят вам определить набор тегов, которые могут быть использованы и какие атрибуты разрешены.
что бы вы ни решили, всегда помните, никогда не доверяйте тому, что входит в ваш PHP-скрипт от пользователя (включая себя!).
все эти ответы великолепны, но, по сути, решение XSS будет заключаться в том, чтобы прекратить генерировать HTML-документы с помощью строковых манипуляций.
фильтрация ввода всегда хорошая идея для любого приложения.
экранирование вывода с помощью htmlentities () и друзей должно работать до тех пор, пока он используется правильно, но это HTML-эквивалент создания SQL-запроса путем объединения строк с mysql_real_escape_string ($var) - он должен работать, но меньше вещей может проверьте свою работу, так сказать, по сравнению с таким подходом, как использование параметризованных запросов.
долгосрочное решение должно быть для приложений, чтобы построить страницу внутри, возможно, используя стандартный интерфейс, как DOM, а затем использовать библиотеку (например, libxml) для обработки сериализации в XHTML/HTML/etc. Конечно, мы очень далеки от того, чтобы быть популярными и достаточно быстрыми, но в то же время мы должны создавать наши HTML-документы с помощью строковых операций, и это по своей сути более рискованно.
Я считаю, что использование этой функции помогает удалить много возможных атак xss: http://www.codebelay.com/killxss.phps
"волшебные цитаты" - это паллиативное средство для некоторых из худших недостатков XSS, которое работает, избегая всего на входе, что-то не так по дизайну. Единственный случай, когда вы хотели бы использовать его, - это когда вы абсолютно должны использовать существующее приложение PHP, которое, как известно, написано небрежно в отношении XSS. (В этом случае у вас серьезные проблемы даже с "волшебными кавычками".) При разработке собственного приложения, вы должны отключить "волшебные кавычки" и следовать практике XSS-safe вместо.
XSS-атак, а межсайтовый скриптинг уязвимость возникает, когда приложение включает в себя строки из внешних источников (данных, вводимых пользователем, выбираются с других сайтов и т. д.) В своей [x]HTML-код, CSS, ECMAScript или другой браузер-анализируется выход без соответствующего побега, надеясь, что специальные символы, такие как "меньше" (в [x]HTML), то одинарные или двойные кавычки (в ECMAScript) никогда не появляются. Правильное решение для этого-всегда экранировать строки в соответствии с правилами языка вывода: использование сущности в [X]HTML, обратные косые черты в ECMAscript и т. д.
потому что это может быть трудно отслеживать то, что является ненадежным и должен быть экранирован, это хорошая идея, чтобы всегда избегать все, что является "текстовая строка", а не "текст с разметкой" на языке, как HTML. Некоторые среды программирования делают это проще, вводя несколько несовместимых типов строк:" строка "(обычный текст)," строка HTML " (разметка HTML) и так далее. Таким образом, прямое неявное преобразование из "строки" в " HTML string " было бы невозможно, и единственный способ, которым строка может стать разметкой HTML, - это передать ее через экранирующую функцию.
"Регистрация глобалов", хотя отключение его, безусловно, хорошая идея, имеет дело с проблемой, полностью отличной от XSS.
сделайте вам любые сеансовые куки (или все куки), которые вы используете HttpOnly. В этом случае большинство браузеров скроют значение cookie из JavaScript. Пользователь может вручную скопировать файлы cookie, но это помогает предотвратить прямой доступ к сценарию. У StackOverflow была эта проблема во время бета-тестирования.
Это не решение, просто еще один кирпич в стене
- Не доверяйте ввод данных пользователем
- Escape все выходные данные свободного текста
- Не используйте magic_quotes; смотрите, если есть СУБД-specfic вариант, или использовать PDO
- рассмотрите возможность использования HTTP-только cookies, где это возможно, чтобы избежать любого вредоносного сценария, способного захватить сеанс
вы должны по крайней мере проверить все данные собираются в базу данных. И попробуйте проверить все данные, выходящие из базы данных тоже.
использования mysql_real_escape_string хороша для предотвращения SQL-инъекции, межсайтовый скриптинг, но это сложнее. Вы должны preg_match, stip_tags или htmlentities, где это возможно!
лучшим текущим методом предотвращения XSS в PHP-приложении является HTML-очиститель (http://htmlpurifier.org/). одним из незначительных недостатков является то, что это довольно большая библиотека и лучше всего использовать с кэшем кода op, таким как APC. Вы будете использовать это в любом месте, где ненадежный контент выводится на экран. Это гораздо более тщательной, что функция htmlentities, функции htmlspecialchars, filter_input, filter_var, strip_tags и т. д.
используйте существующую библиотеку дезинфекции пользовательского ввода для очистки все пользовательский ввод. Если вы не ставите много усилий в него, реализуя его самостоятельно никогда не будет работать, а также.