Для новачків. XSS і помилки розробників на веб-сервісах

Спочатку розберемо, що таке XSS і його види.
XSS — Cross-Site Scripting — Одна з безлічі вразливостей веб додатків, яка дозволяє впровадити шкідливий код, на сторінку.
Є 2 типу XSS:
  1. Пасивна — XSS, яка статично знаходиться на сторінці
  2. Активна — XSS, яка динамічно відображається на сторінці, при певному запиті
За кілька років роботи у сфері інформаційної безпеки, я зміг набратися досвіду і можу розповісти про деяких нетипових видах XSS. Дані типи вразливостей досить поширені на сучасних веб-сервісах, але на жаль через свою незвичайність, вони сховалися в тіні.

Почнемо з помилкових уявлень розробників:
  1. Розробник думає, що XSS — це ін'єкція тільки в HTML-сутність і тільки. Це помилкова думка складається з дня у день. Насправді ж, XSS можуть бути не тільки в HTML, вони можуть бути майже скрізь, наприклад, навіть у картинці.
  2. Розробник впевнений, що відфільтрувавши спец символи, можна захиститися від XSS. Дані думка частково вірно, але в більшості випадків розробники фільтрують тільки лапки (< >) і забувають про апострофи, які потім можуть потрапити в атрибути чого-небудь.
А зараз давайте розберемо кілька типів атаки:
Звичайний тип
Представимо у нас є PHTML (PHP + HTML код
<!DOCTYPE HTML>
<html>
<head>
<title>Привіт!</title>
</head>
<body>
Привіт, <?=(isset($_GET['name']) ? $_GET['name'] : "незнайомець")?>!
</body>
</html>

Даний код виводить
"Привіт, незнайомець!"
, якщо немає GET параметр з ім'ям name, але якщо ж параметр є, то тоді виведе
"Привіт, {$_GET['name']}!"
. За допомогою GET-запиту, робимо запит на наш скрипт:
index.php?name=Admin
. Виводить
"Привіт, Admin!"
.
Тепер спробуємо вивести наш шкідливий код. Для цього робимо запит:
index.php?name=<script>document.write('Hacker')</script>
. Тепер нам виведе
"Привіт, Hacker!"
. Як бачимо, наш код
document.write('Hacker')
виконався.


Так-же можна впроваджувати шкідливий код при впровадженні в атрибути. Для прикладу візьмемо PHTML (PHP + HTML) код:
<html>
<head>
<title>Привіт!</title>
</head>
<body>
Ваше ім'я: <input value="<?=(isset($_GET['name']) ? $_GET['name'] : "незнайомець")?>">
</body>
</html>

Як бачимо, у нас виконався код, де ім'я міститься в input
e (Текстове поле). Тепер для впровадження нашого коду потрібно всього лише зробити запит:
index.php?name=">
. Як бачимо ми додали
">`, тим самим закривши атрибут і тег:


Спосіб захисту:
Для захисту від даної уразливості в PHP передбачена функція
htmlspecialchars
. Використовувати її досить просто — для цього у відрізок PHP-коду просто додамо обробник
htmlspecialchars
Виходить:
<?=(isset($_GET['name']) ? htmlspecialchars($_GET['name']) : "незнайомець")?>

І наші XSS вже не працюють.


Скриптовой тип
Уявімо, що у нас є PHTML (PHP + HTML) код:
<!DOCTYPE HTML>
<html>
<head>
<title>Привіт!</title>
<script>
function deleteNews(id) {
// Видалення новини
alert("Успішно видалено");
}
</script>
</head>
<body>
<a onclick="deleteNews('<?=(isset($_GET['id']) ? htmlspecialchars($_GET['id']) : "0")?>')">Видалити новину</a>
</body>
</html>

Даний код виводить посилання
"Видалити новину"
, де ID новини GET передається в параметрі
id
. За допомогою GET-запиту робимо запит на наш скрипт:
index.php?name='); alert(1);//
. Тепер при натисканні на посилання, виведе наш
alert(1)
, незважаючи на htmlspecialchars. Це відбувається з-за того, що htmlspecialchars не фільтрує за замовчуванням одинарні лапки.
Спосіб захисту:
Є кілька способів захисту:
  • Той же
    htmlspecialchars
    , але на цей раз з параметром ENT_QUOTES. Виходить:
    <?=(isset($_GET['id']) ? htmlspecialchars($_GET['id'], ENT_QUOTES) : "0")?>

  • В даному способі використовується функція
    addslashes
    . Вона екранує ковичкі за допомогою зворотного слеша. Виходить:
    <?=(isset($_GET['id']) ? addslashes($_GET['id']) : "0")?>

    Особисто я не рекомендую цей спосіб захисту, але якщо комусь треба передати в апострофи функцію, тоді дерзайте.
  • Залишити лише числа. У даному способі використовується перетворення в
    integer
    . Виходить:
    <?=(isset($_GET['id']) ? (int)$_GET['id'] : "0")?>

    Таким чином ми залишаємо тільки числа.


Зображення
Багато хто зараз задаються питанням "Чому ж зображення і при чому вони тут взагалі?". У наш час все використовують аватарки, картинки і т. п. Але неправильна фільтрація може спричинити за собою наслідки! Отже, вразливість полягає в тому, що якщо фільтрувати по типу "Зображення" чи ні, то можна дозволити завантаження таких файлів SVG. Що таке SVG (.svg або .svgz)?
SVG — Мова для побудови векторної графіки на XML
Mime-Type для SVG:
image/svg+xml

У чому ж уразливість?
SVG може відображатися в браузерах, але в чому ж небезпека? Як не дивно, але SVG може використовувати JavaScript. Для цього просто потрібно прописати в тег svg атрибут onload. Приклад:
<?xml version="1.0" encoding="UTF-8"?>
<svg version="1.1" baseProfile="tiny" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="480" height="360" onload="alert(document.cookie)">
<image xlink:href="http://my_sniffer/" x="0" y="0" height="50px" width="50px"/>
</svg>

Тепер, якщо завантажити даний файл на сервер (хай буде шлях http://site.ru/uploads/avatar.svg) і перейти по ньому, то виконається код з onload.
Спосіб захисту:
Фільтрувати файли за розширення (.png .jpg, .jpeg) і після чого перевіряти їх валідність.


Посилання
наприклад у нас є скрипт для захисту від OpenRedirect'a на PHTML (PHP + HTML:
<!DOCTYPE HTML>
<html>
<head>
<title>Перехід на небезпечний сайт!</title>
</head>
<body>
<a href="<?=(isset($_GET['url']) ? htmlspecialchars($_GET['url']) : "https://habrahabr.ru")?>">Перейти на небезпечний сайт!</a>
</body>
</html>

Вразливість полягає в тому, що ми можемо використовувати не тільки http || https протоколи, а також javascript і data-протоколи. Для демонстрації перейдемо на сторінку:
script.php?url=javascript:alert(document.cookie);//
. Тепер при натисканні на сторінці посиланням, у нас повилазять наші cookie's.
Спосіб захисту:
Фільтрувати URL по regex
у
/^((http|https)\:\/\/)[a-zA-Z0-9.\/\?\:@-=#]+.([a-zA-Z0-9\&.\/\?\:@-=#])*$/is` і пропускати, тільки посилання проходять його
Рекомендації:
  1. Використовувати спеціальний HTTPHeader:
    X-XSS-Protection
  2. Використовувати спеціальний HTTPHeader:
    Content-Security-Policy
Посилання на ресурси:
https://ru.wikipedia.org/wiki/%D0%9C%D0%B5%D0%B6%D1%81%D0%B0%D0%B9%D1%82%D0%BE%D0%B2%D1%8B%D0%B9_%D1%81%D0%BA%D1%80%D0%B8%D0%BF%D1%82%D0%B8%D0%BD%D0%B3
https://www.owasp.org/index.php/Cross-site_Scripting_%28%58%53%53%29
http://php.net/manual/ru/function.htmlspecialchars.php
http://php.net/manual/ru/function.addslashes.php
https://habrahabr.ru/post/157087/
https://ru.wikipedia.org/wiki/SVG
http://www.w3.org/Graphics/SVG/
https://habrahabr.ru/company/nixsolutions/blog/271575/
https://habrahabr.ru/post/168739/
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.