как лучше всего избегать xss-атак на сайте php?

<p>у меня php настроено так, что магические кавычки включены, а глобальные регистры отключены.</p><p>я делаю все возможное, чтобы всегда вызывать htmlentities () для всего, что я выводил, полученного из пользовательского ввода.</p><p>я также иногда ищу свою базу данных для общих вещей, используемых в xss, таких как ...</p><pre><code><script </code></pre><p>что еще я должен делать и как я могу убедиться, что то, что я пытаюсь сделать, <strong>всегда</strong> сделано.</p>

<p>экранирование ввода - не лучшее, что вы можете сделать для успешного предотвращения xss. также выход должен быть экранирован. если вы используете шаблонизатор smarty, вы можете использовать модификатор <code>|escape:'htmlall'</code> для преобразования всех чувствительных символов в html-объекты (я использую собственный модификатор <code>|e</code>, который является псевдонимом вышеупомянутого).</p><p>мой подход к безопасности ввода/вывода:</p><ul> <li>сохранение пользовательского ввода не изменено (при вводе нет экранирования html, только экранирование с использованием db выполняется с помощью операторов, подготовленных pdo)</li> <li>экранирование на выходе, в зависимости от того, какой формат вывода вы используете (например, html и json нужны разные правила экранирования)</li> </ul>

<p>я придерживаюсь мнения, что нельзя ничего избегать при вводе, только при выводе. поскольку (большую часть времени) вы не можете предполагать, что знаете, куда эти данные отправляются. например, если у вас есть форма, которая принимает данные, которые впоследствии появляются в электронном письме, которое вы отправляете, вам нужно другое экранирование (в противном случае злоумышленник может перезаписать ваши заголовки электронной почты).</p><p>другими словами, вы можете убежать только в самый последний момент, когда данные "покидают" ваше приложение:</p><ul> <li>элемент списка</li> <li>запись в xml-файл, экранирование для xml</li> <li>запись в бд, escape (для этой конкретной субд)</li> <li>написать письмо, бежать по электронной почте</li> <li>так далее</li> </ul><p>чтобы пойти коротко:</p><ol> <li>вы не знаете, куда идут ваши данные</li> <li>данные могут на самом деле оказаться в более чем одном месте, требуя другого механизма выхода, но не оба</li> <li>данные сбежали по неправильной цели, на самом деле не ницца. (например, получите электронное письмо с темой "перейти к бару томми".)</li> </ol><p>esp # 3 произойдет, если вы экранируете данные на входном слое (или вам нужно снова удалить их и т.д.).</p><p>ps: я буду второй совет, чтобы не использовать magic\_quotes, это чистое зло!</p>

<p>есть много способов сделать xss (см. <a href="http://ha.ckers.org/xss.html">http://ha.ckers.org/xss.html</a> ), и это очень трудно поймать.</p><p>я лично делегирую это используемой в настоящее время платформе (например, code igniter). хотя он и не идеален, он может поймать больше, чем мои ручные процедуры.</p>

<blockquote> <p>я делаю все возможное, чтобы всегда вызывать htmlentities () для всего, что я выводил, полученного из пользовательского ввода.</p> <blockquote> <p>.</p> </blockquote> </blockquote><p>see joel's essay on <a href="http://www.joelonsoftware.com/articles/wrong.html">making code look wrong</a> for help with this</p>

<p>я полагаюсь на <a href="http://phptal.motion-twin.com/">phptal</a> для этого.</p><p>в отличие от smarty и простого php, он по умолчанию экранирует все выходные данные. это большой выигрыш для безопасности, потому что ваш сайт не станет уязвимым, если вы забудете где-нибудь <code>htmlspecialchars()</code> или <code>|escape</code>.</p><p>xss - это специфическая для html атака, поэтому вывод html - подходящее место для ее предотвращения. вы не должны пытаться предварительно фильтровать данные в базе данных, потому что вам может потребоваться вывести данные на другой носитель, который не принимает html, но имеет свои собственные риски.</p>

<p><strong>библиотека шаблонов.</strong> или, по крайней мере, именно так должны поступать библиотеки шаблонов. для предотвращения xss <em> все </em> выходные данные должны быть закодированы. это не задача основной логики приложения/управления, она должна обрабатываться исключительно методами вывода.</p><p>если вы разбросали htmlentities () по всему коду, общий дизайн будет неправильным. и, как вы предлагаете, вы можете пропустить одно или два места. вот почему единственным решением является строгая кодировка html <em> -> когда </em> выходные переменные записываются в поток html/xml.</p><p>к сожалению, большинство библиотек шаблонов php только добавляют собственный синтаксис шаблонов, но не заботятся о кодировке вывода, или локализации, или проверке html, или чем-то важном. может, кто-то еще знает правильную библиотеку шаблонов для php?</p>

<p>если вы обеспокоены атаками xss, решение проблемы заключается в кодировании выходных строк в html. если вы не забываете кодировать каждый отдельный выходной символ в формат html, невозможно выполнить успешную xss-атаку.</p><p>подробнее: <a href="http://www.diovo.com/2008/09/sanitizing-user-data-how-and-where-to-do-it/">очистка пользовательских данных: как и где это сделать</a> </p>

<p>лично я бы отключил magic\_quotes. в php5 + он отключен по умолчанию, и лучше кодировать его так, как будто его вообще нет, поскольку он не скрывает все и будет удален из php6.</p><p>затем, в зависимости от того, какой тип пользовательских данных вы фильтруете, будет диктоваться, что делать дальше, например, если это просто текст, например имя, затем <code>strip\_tags(trim(stripslashes()));</code> это или для проверки диапазонов используйте регулярные выражения.</p><p>если вы ожидаете определенный диапазон значений, создайте массив допустимых значений и пропустите эти значения только через (<code>in\_array($userdata, array(...))).если вы проверяете числа, используйте is_numeric для принудительного применения целых чисел или приведения к определенному типу, что должно препятствовать тому, чтобы люди пытались отправлять строки вместо них.если у вас php5.2 +, подумайте о том, чтобы посмотреть <a href="http://ca.php.net/filter">filter () и использовать это расширение, которое может фильтровать различные типы данных, включая адреса электронной почты. документация не особенно хороша, но улучшается.если вам нужно обрабатывать html, вы должны рассмотреть что-то вроде <a href="http://cyberai.users.phpclasses.org/browse/package/2189.html">php input filter или <a href="http://htmlpurifier.org/">html purifier . html purifier также проверит html на соответствие. я не уверен, что входной фильтр все еще разрабатывается. оба позволят вам определить набор тегов, которые можно использовать, и какие атрибуты разрешены.что бы вы ни выбрали, всегда помните, никогда не доверяйте ничему, поступающему в ваш сценарий php от пользователя (включая вас!).

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

"магические кавычки" - это паллиативное средство от некоторых худших недостатков xss, которые работают, избегая всего на входе, что-то не так по замыслу. единственный случай, когда вы захотите его использовать, - это когда вам абсолютно необходимо использовать существующее php приложение, о котором известно, что оно написано небрежно в отношении xss. (в этом случае у вас серьезные проблемы даже с "магическими кавычками".) при разработке собственного приложения вы должны отключить "магические кавычки" и следовать правилам, безопасным для xss.xss, уязвимость межсайтового скриптинга, возникает, когда приложение включает строки из внешних источников (пользовательский ввод, выборка с других веб-сайтов и т.д.) в свои [x] html, css, ecmascript или другие выходные данные, анализируемые браузером, без надлежащего экранирования, надеясь что специальные символы, такие как меньше чем (в [x] html), одинарные или двойные кавычки (ecmascript), никогда не появятся. правильное решение - всегда экранировать строки в соответствии с правилами языка вывода: используя сущности в [x] html, обратную косую черту в ecmascript и т.д.поскольку может быть трудно отследить то, что ненадежно и должно быть экранировано, хорошая идея всегда избегать всего, что является "текстовой строкой", в отличие от "текста с разметкой" в языке, таком как html. в некоторых средах программирования это упрощается за счет введения нескольких несовместимых типов строк: "строка" (обычный текст), "строка html" (разметка html) и так далее. таким образом, прямое неявное преобразование из "строки" в "строку html" было бы невозможно, и единственный способ, которым строка может стать разметкой html, - это передать ее через экранирующую функцию."зарегистрировать глобальные переменные", хотя их отключение - определенно хорошая идея, решает проблему, совершенно отличную от xss.

все эти ответы великолепны, но, по сути, решением xss будет прекращение генерации документов html путем манипулирования строками.фильтрация входных данных всегда хорошая идея для любого приложения.экранирование вывода с помощью htmlentities () и друзей должно работать до тех пор, пока он используется правильно, но это html-эквивалент создания sql-запроса путем объединения строк с mysql_real_escape_string ($ var) - это должно работать, но меньше вещей может проверить вашу работу так сказать, по сравнению с подходом, подобным использованию параметризованных запросов.</p><p>долгосрочное решение должно состоять в том, чтобы приложения создавали страницу внутренне, возможно, используя стандартный интерфейс, такой как dom, а затем использовали библиотеку (например, libxml) для обработки сериализации в xhtml/html/и т.д. конечно, мы далеки от того, чтобы быть популярными и достаточно быстрыми, но в то же время мы должны создавать наши html-документы с помощью строковых операций, и это по своей природе более рискованно.</p>

<ul> <li>не доверяйте вводу пользователя</li> <li>сбросить все выходные тексты</li> <li>не используйте magic\_quotes; посмотрите, есть ли вариант, специфичный для субд, или используйте pdo</li> <li>рассмотрите возможность использования файлов cookie только для http, чтобы избежать любого вредоносного сценария, способного перехватить сеанс</li> </ul>

<p>вы должны по крайней мере проверить все данные, поступающие в базу данных. и попробуйте проверить все данные, покидающие базу данных тоже.</p><p>mysql\_real\_escape\_string хорош для предотвращения внедрения sql, но xss сложнее. вы должны использовать preg\_match, assign\_tags или htmlentities, где это возможно!</p>

<p>на сегодняшний день лучшим методом предотвращения xss в приложении php является html purifier (http://htmlpurifier.org/). один небольшой недостаток заключается в том, что это довольно большая библиотека, и ее лучше всего использовать с кэшем кода операции, таким как apc. вы можете использовать это в любом месте, где ненадежный контент выводится на экран. гораздо тщательнее htmlentities, htmlspecialchars, filter\_input, filter\_var, strip\_tags и т.д.</p>

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

<p>используйте существующую пользовательскую библиотеку очистки для очистки <em>все</em> пользовательский ввод. если вы не приложите <em>много</em> усилий, реализация этого самостоятельно никогда не сработает.</p>