Каковы наилучшие методы предотвращения xss-атак на PHP-сайте


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

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

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

<script

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

Author: Rik Heywood, 2008-09-16

20 answers

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

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

  • сохраняйте пользовательский ввод без изменений (без экранирования HTML при вводе, только экранирование с учетом базы данных, выполняемое с помощью подготовленных инструкций PDO)
  • побег при выводе, в зависимости от того, какой формат вывода вы используете (например, HTML и JSON требуют разных правил экранирования)
 58
Author: Michał Rudnicki, 2008-09-16 11:41:23

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

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

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

Короче говоря:

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

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

PS: Я поддержу совет не использовать magic_quotes, это чистое зло!

 18
Author: Jilles, 2008-09-16 21:32:29

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

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

 12
Author: Christian Studer, 2008-09-16 11:38:17

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

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

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

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

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

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

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

 10
Author: Matt Farina, 2008-09-16 12:13:45

Рих Пишет:

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

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

 7
Author: Mason, 2008-09-16 19:13:19

В этом я полагаюсь на PHPTAL.

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

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

 4
Author: Kornel, 2009-11-25 21:07:32

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

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

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

 4
Author: user319490, 2010-04-18 02:01:08

Для большинства сайтов достаточно избежать всего пользовательского ввода. Также убедитесь, что идентификаторы сеансов не попадают в URL-адрес, чтобы их нельзя было украсть из ссылки Referer на другой сайт. Кроме того, если вы разрешаете своим пользователям отправлять ссылки, убедитесь, что ссылки на протокол javascript: не разрешены; они выполнят сценарий, как только пользователь нажмет на ссылку.

 2
Author: Konrad Rudolph, 2008-09-16 11:24:39

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

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

 2
Author: Niyaz, 2008-09-16 11:40:58

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

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

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

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

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

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

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

 2
Author: , 2008-09-16 19:09:23

Все эти ответы великолепны, но, по сути, решение XSS будет заключаться в том, чтобы прекратить генерировать HTML-документы путем манипулирования строками.

Фильтрация входных данных всегда является хорошей идеей для любого приложения.

Экранирование вашего вывода с помощью htmlentities() и друзей должно работать до тех пор, пока оно используется правильно, но это HTML-эквивалент создания SQL-запроса путем объединения строк с mysql_real_escape_string($var) - это должно работать, но меньше вещей может подтвердить ваш работа, так сказать, по сравнению с подходом, подобным использованию параметризованных запросов.

Долгосрочное решение должно заключаться в том, чтобы приложения создавали страницу внутри, возможно, используя стандартный интерфейс, такой как DOM, а затем использовали библиотеку (например, libxml) для обработки сериализации в XHTML/HTML/и т.д. Конечно, мы далеки от того, чтобы быть популярными и достаточно быстрыми, но в то же время мы должны создавать наши HTML-документы с помощью строковых операций, и это по своей сути больше рискованный.

 2
Author: Daniel Papasian, 2008-09-16 21:24:32

Я нахожу, что использование этой функции помогает исключить множество возможных атак xss: http://www.codebelay.com/killxss.phps

 2
Author: barce, 2008-09-16 21:35:01

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

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

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

"Регистрация глобалов", хотя ее отключение, безусловно, является хорошей идеей, решает проблему, совершенно отличную от XSS.

 2
Author: Alexey Feldgendler, 2010-11-11 15:48:44

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

Это не решение, просто еще один кирпич в стене

 1
Author: basszero, 2008-09-16 12:17:07
  • Не доверяйте пользовательскому вводу
  • Экранировать весь вывод свободного текста
  • Не используйте magic_quotes; посмотрите, есть ли вариант, специфичный для СУБД, или используйте PDO
  • Рассмотрите возможность использования файлов cookie только HTTP, где это возможно, чтобы избежать любого вредоносного сценария, способного перехватить сеанс
 1
Author: Rob, 2008-09-16 21:28:06

Вы должны, по крайней мере, проверить все данные, поступающие в базу данных. И попытайтесь также проверить все данные, покидающие базу данных.

Строка Mysql_real_escape_string хороша для предотвращения внедрения SQL, но XSS сложнее. Вы должны по возможности указывать preg_match, stip_tags или htmlentities!

 1
Author: Abeon, 2010-04-19 23:54:53

Лучшим текущим методом предотвращения XSS в PHP-приложении является очиститель HTML (http://htmlpurifier.org /). Одним из незначительных недостатков этого является то, что это довольно большая библиотека, и ее лучше всего использовать с кэшем операционного кода, таким как APC. Вы бы использовали это в любом месте, где на экран выводится ненадежный контент. Это гораздо более тщательно, чем htmlentities, htmlspecialchars, filter_input, filter_var, strip_tags и т.д.

 1
Author: Night Owl, 2011-04-24 18:36:55

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

 0
Author: dbr, 2008-09-16 12:04:44

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

 0
Author: Darren22, 2008-09-16 21:37:34

Сложно реализовать тщательное предотвращение инъекций sql/xss на сайте, который не вызывает ложных срабатываний. В CMS конечный пользователь может захотеть использовать <script> или <object>, которые ссылаются на элементы с другого сайта.

Я рекомендую всем пользователям устанавливать Firefox с помощью NoScript;-)

 -1
Author: Adam, 2015-12-17 11:51:31