Як запобігти XSS за допомогою HTML / PHP?


256

Як я можу запобігти XSS (міжсайтовий сценарій), використовуючи лише HTML та PHP?

Я бачив численні інші публікації на цю тему, але не знайшов статті, яка чітко і стисло визначає, як насправді запобігти XSS.


3
Лише зауважте, що це не вирішить випадок, коли ви можете використовувати введення користувача як атрибут HTML. Наприклад, вихідна URL-адреса зображення. Не звичайний випадок, але простий у забутті.
Майкл Міор

@MichaelMior тут є рішенням для запобігання XSS в hrefабо srcатрибут HTML: stackoverflow.com/questions/19047119 / ...
baptx

Там хороша стаття тут , що пояснює XSS і як запобігти його на різних мовах ( в тому числі. PHP).
XCore

Відповіді:


296

В основному, вам потрібно використовувати цю функцію, htmlspecialchars()коли ви хочете вивести щось на браузер, який прийшов із введення користувача.

Правильний спосіб використання цієї функції виглядає приблизно так:

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

Університет Google Code також має такі навчальні відео з веб-безпеки:


7
@TimTim: У більшості випадків так. Однак, коли вам потрібно дозволити введення HTML- кодів
Alix Axel

@Alix Axel, так це ваша відповідь на використання htmlspecialchars або на htmlpurifier.org ?
TimTim

3
Якщо вам потрібно прийняти введення HTML, використовуйте HTML очищувач, якщо не використовуйте htmlspecialchars().
Алікс Аксель

9
htmlspecialchars або htmlentities? Перевірте тут stackoverflow.com/questions/46483 / ...
kiranvj

4
Більшість випадків це правильно, але це не так просто. Вам слід розглянути питання про те, як увімкнути ненадійний рядок у HTML, Js, Css та поставити ненадійний HTML у HTML. Подивіться на це: owasp.org/index.php/…
бронзовий чоловік

41

Одне з моїх улюблених посилань на OWASP - це пояснення сценарію крос-сайтів, оскільки, хоча існує велика кількість XSS-векторів атак, наступне з кількох правил може захищати проти більшості з них сильно!

Це чіт-лист безпеки для PHP


7
Я теж .. Це XSS Cheat Sheet Sheet Sheet owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet

1
Не зовсім XSS, але я думаю, що XSS та CSRF зазвичай змішуються, і обидва справді небезпечні: owasp.org/index.php/…
Саймон

2
Ця сторінка більше не існує
Mazzy


15

Один з найважливіших кроків - це очистити будь-які дані користувача перед його обробкою та / або поверненням до браузера. PHP має деякі функції " фільтра ", які можна використовувати.

Форма, яку зазвичай мають атаки XSS, полягає в тому, щоб вставити посилання на якийсь веб-сайт javascript, який містить зловмисні наміри для користувача. Детальніше про це читайте тут .

Ви також захочете протестувати свій сайт - я можу порекомендувати надбудову Firefox XSS Me .


Що мені потрібно, щоб переконатися, що я саме проводжу санітарну інформацію. Чи є один конкретний символ / рядок, на який я повинен стежити?
TimTim

27
@TimTim - ні. Все що вводяться користувачем , повинні завжди розглядатися як по своїй суті ворожі.
zombat

Крім того, внутрішні дані (співробітники, системдмін тощо) можуть бути небезпечними. Ви повинні ідентифікувати та контролювати (з датою журналу та користувачем) дані, що відображаються з інтерпретацією.
Самуель Доусон

9

У порядку вподобання:

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

Крім того, переконайтеся, що ви втекли на виході, а не на вході .


7

Перехресне повідомлення про це як консолідована посилання з бета-документації SO, яка переходить в автономний режим.

Проблема

Межсайтовий сценарій - це ненавмисне виконання віддаленого коду веб-клієнтом. Будь-яка веб-програма може піддатися дії 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 скрипт , щоб бути продезінфікувати або підтверджено в багатьох відносинах . Вони корисні при збереженні або виведенні вводу клієнта.

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


5

Багато рамок допомагають обробляти 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);
}

2

Ви також можете встановити деякі відповідні заголовки відповідей HTTP через header(...)

X-XSS-захист "1; режим = блок"

щоб бути впевненим, увімкнено режим захисту браузера XSS.

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

щоб увімкнути захист вмісту на стороні браузера. Дивіться цю інформацію щодо детальної політики щодо безпеки вмісту (CSP): http://content-security-policy.com/ Особливо налаштування CSP для блокування вбудованих сценаріїв та зовнішніх джерел скриптів корисно проти XSS.

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


1
<?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('#([a-z]*)[\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('#([a-z]*)[\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('#([a-z]*)[\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;
}

5
Ви не повинні використовувати так, preg_replaceяк він використовується evalна вашому вході. owasp.org/index.php/PHP_Security_Cheat_Sheet#Code_Injection
CrabLab

0

Використовуйте htmlspecialcharsна PHP. На HTML намагайтеся уникати використання:

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

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

Крім того, очевидно, намагайтеся уникати eval(var), якщо вам доведеться використовувати будь-який з них, тоді спробуйте уникнути JS , HTML уникнути їх, і вам, можливо, доведеться зробити ще трохи, але для основ цього має бути достатньо.


0

Найкращий спосіб захистити свої дані - це htmlentitiesфункція використання . Приклад:

htmlentities($target, ENT_QUOTES, 'UTF-8');

Більше інформації ви можете отримати тут .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.