Каковы лучшие практики для предотвращения атак xss на сайте PHP - PullRequest
65 голосов
/ 16 сентября 2008

Я настроил PHP так, что магические кавычки включены, а глобальные регистры отключены.

Я прилагаю все усилия, чтобы всегда вызывать htmlentities () для всего, что я выводил, полученного из пользовательского ввода.

Я также иногда ищу свою базу данных для общих вещей, используемых в xss, таких как ...

<script

Что еще я должен делать и как я могу убедиться, что то, что я пытаюсь сделать, всегда сделано.

Ответы [ 20 ]

58 голосов
/ 16 сентября 2008

Экранирующий ввод - не лучшее, что вы можете сделать для успешного предотвращения XSS. Также выход должен быть экранирован. Если вы используете шаблонизатор Smarty, вы можете использовать модификатор |escape:'htmlall' для преобразования всех чувствительных символов в объекты HTML (я использую собственный модификатор |e, который является псевдонимом вышеупомянутого).

Мой подход к безопасности ввода / вывода:

  • сохранение пользовательского ввода не изменено (при вводе не экранируется HTML, только экранирование с использованием БД выполняется с помощью подготовленных инструкций PDO)
  • экранирование на выходе, в зависимости от того, какой формат вывода вы используете (например, HTML и JSON нужны разные правила экранирования)
18 голосов
/ 17 сентября 2008

Я считаю, что нельзя ничего избегать во время ввода, только на выходе. Поскольку (большую часть времени) вы не можете предполагать, что знаете, куда эти данные отправляются. Например, если у вас есть форма, которая принимает данные, которые впоследствии появляются в электронном письме, которое вы отправляете, вам нужно другое экранирование (в противном случае злоумышленник может переписать ваши заголовки электронной почты).

Другими словами, вы можете скрыться только в самый последний момент, когда данные «покидают» ваше приложение:

  • Элемент списка
  • Запись в XML-файл, экранирование для XML
  • Запись в БД, escape (для этой конкретной СУБД)
  • Написать письмо, бежать по электронной почте
  • и т.д.

Чтобы пойти коротко:

  1. Вы не знаете, куда отправляются ваши данные
  2. Данные могут на самом деле оказаться в более чем одном месте, требуя другого механизма выхода, НО НЕ ОБА
  3. Данные, сбежавшие из-за неправильной цели, действительно не хороши. (Например, получите электронное письмо с темой «Перейти к бару Томми».)

Esp # 3 произойдет, если вы экранируете данные на входном слое (или вам нужно снова удалить их и т. Д.).

PS: я буду вторым советом не использовать magic_quotes, это чистое зло!

12 голосов
/ 16 сентября 2008

Существует множество способов сделать XSS (см. http://ha.ckers.org/xss.html), и его очень трудно поймать.

Я лично делегирую это текущей используемой платформе (например, Code Igniter). Хотя он и не идеален, он может поймать больше, чем мои ручные процедуры.

10 голосов
/ 16 сентября 2008

Это отличный вопрос.

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

Когда вы идете представить свой фильтр данных, что не должно быть там. Например, если нет причины присутствия JavaScript, найдите его и удалите. Самый простой способ сделать это - использовать функцию strip_tags и отображать только те HTML-теги, которые вы разрешаете.

Затем возьмите то, что у вас есть, и передайте его htmlentities или htmlspecialchars, чтобы изменить то, что там, на символы ascii. Делайте это в зависимости от контекста и того, что вы хотите получить.

Я бы также предложил отключить магические кавычки. Он был удален из PHP 6 и считается плохой практикой его использования. Подробности на http://us3.php.net/magic_quotes

Для более подробной информации проверьте http://ha.ckers.org/xss.html

Это не полный ответ, но, надеюсь, достаточно, чтобы помочь вам начать.

7 голосов
/ 16 сентября 2008

Рих пишет:

Я прилагаю все усилия, чтобы всегда вызывать htmlentities () для всего, что я выводил, полученного из пользовательского ввода.

См. Эссе Джоэла по Как выглядит код неправильно , чтобы получить помощь по этому

4 голосов
/ 16 октября 2008

Я полагаюсь на PHPTAL для этого.

В отличие от Smarty и обычного PHP, он по умолчанию экранирует все выходные данные. Это большой выигрыш для безопасности, потому что ваш сайт не станет уязвимым, если вы забудете htmlspecialchars() или |escape где-то.

XSS - это атака, специфичная для HTML, поэтому вывод HTML является подходящим местом для ее предотвращения. Вы не должны пытаться предварительно фильтровать данные в базе данных, потому что вам может потребоваться вывести данные на другой носитель, который не принимает HTML, но имеет свои собственные риски.

4 голосов
/ 18 апреля 2010

Библиотека шаблонов. Или, по крайней мере, именно так должны поступать библиотеки шаблонов. Для предотвращения XSS все выходные данные должны быть закодированы. Это не задача основной логики приложения / управления, она должна обрабатываться исключительно методами вывода.

Если вы разбросали htmlentities () по всему своему коду, общий дизайн будет неправильным. И, как вы предлагаете, вы можете пропустить одно или два места. Вот почему единственное решение - строгая кодировка html -> когда выходные переменные записываются в поток html / xml.

К сожалению, большинство библиотек шаблонов php только добавляют собственный синтаксис шаблонов, но не заботятся о кодировке вывода, локализации, проверке html или о чем-либо важном. Может быть, кто-то еще знает правильную библиотеку шаблонов для php?

2 голосов
/ 16 сентября 2008

Лично я бы отключил magic_quotes. В PHP5 + он отключен по умолчанию, и лучше кодировать его так, как будто его совсем нет, так как он не скрывает всего и будет удален из PHP6.

Далее, в зависимости от того, какой тип пользовательских данных вы фильтруете, будет диктоваться, что делать дальше, например. если это просто текст, например имя, затем strip_tags(trim(stripslashes())); оно или для проверки диапазонов используйте регулярные выражения.

Если вы ожидаете определенный диапазон значений, создайте массив допустимых значений и пропустите эти значения только через (in_array($userData, array(...))).

Если вы проверяете числа, используйте is_numeric для принудительного применения целых чисел или приведения к определенному типу, что должно препятствовать тому, чтобы люди пытались отправлять строки вместо.

Если у вас PHP5.2 +, подумайте о filter () и использовании этого расширения, которое может фильтровать различные типы данных, включая адреса электронной почты. Документация не особенно хороша, но улучшается.

Если вам нужно обработать HTML, вам следует рассмотреть что-то вроде Фильтр ввода PHP или Очиститель HTML . HTML Purifier также проверит HTML на соответствие. Я не уверен, что входной фильтр все еще разрабатывается. Оба позволят вам определить набор тегов, которые можно использовать, и какие атрибуты разрешены.

Что бы вы ни выбрали, всегда помните, никогда не доверяйте ничему, что входит в ваш PHP-скрипт от пользователя (включая вас!).

2 голосов
/ 16 сентября 2008

«Магические кавычки» - это паллиативное средство от некоторых наихудших недостатков XSS, которое работает, избегая всего на входе, что-то не так по замыслу. Единственный случай, когда вы захотите использовать его, это когда вам абсолютно необходимо использовать существующее PHP-приложение, о котором известно, что оно написано небрежно в отношении XSS. (В этом случае у вас серьезные проблемы даже с «магическими кавычками».) При разработке собственного приложения вы должны отключить «магические кавычки» и следовать правилам, безопасным для XSS.

XSS, уязвимость межсайтового скриптинга, возникает, когда приложение включает строки из внешних источников (пользовательский ввод, выборка с других веб-сайтов и т. Д.) В свои [X] HTML, CSS, ECMAscript или другие выходные данные, анализируемые браузером, без надлежащего бежать, надеясь, что специальные символы, такие как «меньше» (в [X] HTML), одинарные или двойные кавычки (ECMAscript), никогда не появятся. Правильное решение - всегда экранировать строки в соответствии с правилами языка вывода: используя сущности в [X] HTML, обратную косую черту в ECMAscript и т. Д.

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

«Зарегистрировать глобальные переменные», хотя их отключение, безусловно, хорошая идея, решает проблему, совершенно отличную от XSS.

2 голосов
/ 16 сентября 2008

Если вы обеспокоены атаками XSS, решение проблемы заключается в кодировании выходных строк в HTML. Если вы не забываете кодировать каждый выходной символ в HTML-формате, то нет способа выполнить успешную XSS-атаку.

Подробнее: Очистка пользовательских данных: как и где это сделать

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...