Как предотвратить XSS с HTML / PHP?

Как предотвратить XSS (межсайтовый скриптинг), используя только HTML и PHP?

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

Solutions Collecting From Web of "Как предотвратить XSS с HTML / PHP?"

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

Правильный способ использования этой функции:

 echo htmlspecialchars($string, ENT_QUOTES, 'UTF-8'); 

В Google Code University также есть эти образовательные видеоролики в Web Security:

  • Как разбить веб-программное обеспечение – посмотрите на уязвимости безопасности в веб-программном обеспечении

  • Что каждый инженер должен знать о безопасности и где его изучать

Одна из моих любимых ссылок OWASP – это объяснение межсайтовых сценариев, потому что, хотя существует большое количество векторов атаки XSS, некоторые из немногих правил могут защитить от большинства из них очень!

Это PHP Cheat Sheet

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

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

Вы также захотите проверить свой сайт – я могу порекомендовать дополнение Firefox XSS Me .

В порядке предпочтения:

  1. Если вы используете механизм шаблонов (например, Twig, Smarty, Blade), убедитесь, что он предлагает контекстно-зависимое экранирование. Я знаю по опыту, что делает Твиг. {{ var|e('html_attr') }}
  2. Если вы хотите разрешить HTML, используйте HTML Purifier . Даже если вы считаете, что принимаете только Markdown или ReStructuredText, вы все равно хотите очистить HTML эти языки разметки.
  3. В противном случае используйте htmlentities($var, ENT_QUOTES | ENT_HTML5, $charset) и убедитесь, что в остальной части вашего документа используется тот же набор символов, что и $charset . В большинстве случаев 'UTF-8' является желаемым набором символов.

Кроме того, убедитесь, что вы выходите на выход, а не на входе .

 <?php function xss_clean($data) { // Fix &entity\n; $data = str_replace(array('&amp;','&lt;','&gt;'), array('&amp;amp;','&amp;lt;','&amp;gt;'), $data); $data = preg_replace('/(&#*\w+)[\x00-\x20]+;/u', '$1;', $data); $data = preg_replace('/(&#x*[0-9A-F]+);*/iu', '$1;', $data); $data = html_entity_decode($data, ENT_COMPAT, 'UTF-8'); // Remove any attribute starting with "on" or xmlns $data = preg_replace('#(<[^>]+?[\x00-\x20"\'])(?:on|xmlns)[^>]*+>#iu', '$1>', $data); // Remove javascript: and vbscript: protocols $data = preg_replace('#([az]*)[\x00-\x20]*=[\x00-\x20]*([`\'"]*)[\x00-\x20]*j[\x00-\x20]*a[\x00-\x20]*v[\x00-\x20]*a[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2nojavascript...', $data); $data = preg_replace('#([az]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*v[\x00-\x20]*b[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2novbscript...', $data); $data = preg_replace('#([az]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*-moz-binding[\x00-\x20]*:#u', '$1=$2nomozbinding...', $data); // Only works in IE: <span style="width: expression(alert('Ping!'));"></span> $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?expression[\x00-\x20]*\([^>]*+>#i', '$1>', $data); $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?behaviour[\x00-\x20]*\([^>]*+>#i', '$1>', $data); $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:*[^>]*+>#iu', '$1>', $data); // Remove namespaced elements (we do not need them) $data = preg_replace('#</*\w+:\w[^>]*+>#i', '', $data); do { // Remove really unwanted tags $old_data = $data; $data = preg_replace('#</*(?:applet|b(?:ase|gsound|link)|embed|frame(?:set)?|i(?:frame|layer)|l(?:ayer|ink)|meta|object|s(?:cript|tyle)|title|xml)[^>]*+>#i', '', $data); } while ($old_data !== $data); // we are done... return $data; } 

Вы также можете установить некоторые заголовки ответа HTTP, связанные с XSS, через header(...)

X-XSS-Protection "1; mode = block"

Разумеется, включен режим защиты браузера XSS.

Content-Security-Policy "default-src 'self'; …"

для обеспечения безопасности на стороне браузера. См. Этот раздел для сведений о политике безопасности контента (CSP): http://content-security-policy.com/. Особенно важно настроить CSP для блокировки встроенных скриптов и внешних источников скриптов, что полезно для XSS.

для общей группы полезных заголовков HTTP-ответов, касающихся безопасности вашего webapp, посмотрите на OWASP: https://www.owasp.org/index.php/List_of_useful_HTTP_headers

Многие структуры помогают обрабатывать XSS по-разному. Когда вы катаетесь самостоятельно или если есть какая-то проблема XSS, мы можем использовать filter_input_array (доступно в PHP 5> = 5.2.0, PHP 7.) Обычно я добавляю этот фрагмент к моему SessionController, потому что все вызовы проходят там до любого другого контроллера взаимодействует с данными. Таким образом, все входные данные пользователя дезинфицируются в одном центральном месте. Если это делается в начале проекта или до того, как ваша база данных отравлена, у вас не должно быть никаких проблем в момент выхода … останавливает мусор, мусор.

 /* Prevent XSS input */ $_GET = filter_input_array(INPUT_GET, FILTER_SANITIZE_STRING); $_POST = filter_input_array(INPUT_POST, FILTER_SANITIZE_STRING); /* I prefer not to use $_REQUEST...but for those who do: */ $_REQUEST = (array)$_POST + (array)$_GET + (array)$_REQUEST; 

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


Если ваша база данных уже отравлена ​​или вы хотите иметь дело с XSS во время вывода, OWASP рекомендует создавать пользовательскую функцию-обертку для echo и использовать ее в любом случае вы выставляете значения, заданные пользователем:

 //xss mitigation functions function xssafe($data,$encoding='UTF-8') { return htmlspecialchars($data,ENT_QUOTES | ENT_HTML401,$encoding); } function xecho($data) { echo xssafe($data); } 

Используйте htmlspecialchars на PHP . На HTML старайтесь избегать использования:

element.innerHTML = “…”; element.outerHTML = “…”; document.write(…); document.writeln(…);

где var контролируется пользователем .

Также, очевидно, избегайте eval(var) , если вам нужно использовать любой из них, тогда попробуйте JS, избегая их, HTML убегает от них, и вам, возможно, придется сделать еще несколько, но для основ этого должно быть достаточно.

Перекрестная проводка это как сводная ссылка из бета-версии SO Documentation, которая отключается.

проблема

Межсайтовый скриптинг – это непреднамеренное выполнение удаленным кодом веб-клиентом. Любое веб-приложение может оказаться в XSS, если оно принимает входные данные от пользователя и выводит его непосредственно на веб-страницу. Если ввод включает HTML или JavaScript, удаленный код может быть выполнен, когда этот контент отображается веб-клиентом.

Например, если сторонняя сторона содержит файл JavaScript:

 // http://example.com/runme.js document.write("I'm running"); 

И приложение PHP напрямую выводит строку, переданную в нее:

 <?php echo '<div>' . $_GET['input'] . '</div>'; 

Если неконтролируемый параметр GET содержит <script src="http://example.com/runme.js"></script> то вывод скрипта PHP будет:

 <div><script src="http://example.com/runme.js"></script></div> 

Будет запущен сторонний JavaScript, и пользователь увидит «Я запущен» на веб-странице.

Решение

Как правило, никогда не доверяйте вводам, поступающим от клиента. Каждое значение GET, POST и cookie может быть вообще чем угодно и поэтому должно быть проверено. При выводе любого из этих значений избегайте их, чтобы они не были оценены неожиданным образом.

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

PHP предоставляет несколько способов избежать вывода в зависимости от контекста.

Функции фильтра

Функции фильтров PHP позволяют входным данным для скрипта php быть подвергнутым санитарной обработке или проверке многими способами . Они полезны при сохранении или выводе на вход клиента.

Кодирование HTML

htmlspecialchars преобразует любые «специальные символы HTML» в свои кодировки HTML, то есть они не будут обрабатываться как стандартный HTML. Чтобы исправить наш предыдущий пример, используя этот метод:

 <?php echo '<div>' . htmlspecialchars($_GET['input']) . '</div>'; // or echo '<div>' . filter_input(INPUT_GET, 'input', FILTER_SANITIZE_SPECIAL_CHARS) . '</div>'; 

Выпустил бы:

 <div>&lt;script src=&quot;http://example.com/runme.js&quot;&gt;&lt;/script&gt;</div> 

Все внутри <div> не будет интерпретироваться как тег JavaScript браузером, а вместо этого как простой текстовый узел. Пользователь будет безопасно видеть:

 <script src="http://example.com/runme.js"></script> 

Кодирование URL

При выводе динамически созданного URL-адреса PHP предоставляет функцию urlencode для безопасного вывода допустимых URL-адресов. Так, например, если пользователь может вводить данные, которые становятся частью другого параметра GET:

 <?php $input = urlencode($_GET['input']); // or $input = filter_input(INPUT_GET, 'input', FILTER_SANITIZE_URL); echo '<a href="http://example.com/page?input="' . $input . '">Link</a>'; 

Любой вредоносный ввод будет преобразован в параметр кодированного URL.

Использование специализированных внешних библиотек или списков OWASP AntiSamy

Иногда вам нужно отправить HTML или другие входы кода. Вам необходимо будет сохранить список авторизованных слов (белый список) и неавторизованный (черный список).

Вы можете загружать стандартные списки, доступные на веб-сайте OWASP AntiSamy . Каждый список подходит для определенного вида взаимодействия (ebay api, tinyMCE и т. Д.). И это с открытым исходным кодом.

Существуют библиотеки, существующие для фильтрации HTML и предотвращения атак XSS для общего случая и выполнения как минимум, а также списков AntiSamy с очень простым использованием. Например, у вас есть очиститель HTML