Angular
Чек-лист
Чек-лист звідси.
Що таке Angular
Angular - це потужний та відкритий фронтенд-фреймворк, який підтримується Google. Він використовує TypeScript для покращення зрозумілості коду та налагодження. З міцними механізмами безпеки Angular запобігає поширеним вразливостям на клієнтській стороні, таким як XSS та відкриті перенаправлення. Його можна використовувати також на стороні сервера, тому важливо враховувати аспекти безпеки з обох сторін.
Архітектура фреймворку
Для кращого розуміння основ Angular давайте розглянемо його основні концепції.
Зазвичай загальний проект Angular виглядає так:
Згідно з документацією, кожне додаток Angular має принаймні один компонент, кореневий компонент (AppComponent
), який з'єднує ієрархію компонентів з DOM. Кожен компонент визначає клас, який містить дані та логіку додатка, і пов'язаний з HTML-шаблоном, який визначає вид, що відображається в цільовому середовищі. Декоратор @Component()
ідентифікує клас нижче як компонент та надає шаблон та пов'язані з компонентом метадані. AppComponent
визначений у файлі app.component.ts
.
Angular NgModules визначають контекст компіляції для набору компонентів, який призначений для домену додатка, робочого процесу або тісно пов'язаного набору можливостей. У кожному додатку Angular є кореневий модуль, зазвичай названий AppModule
, який надає механізм завантаження, що запускає додаток. Зазвичай додаток містить багато функціональних модулів. AppModule
визначений у файлі app.module.ts
.
Модуль маршрутизатора Angular Router
надає сервіс, який дозволяє визначити шлях навігації між різними станами додатка та ієрархіями видів у вашому додатку. RouterModule
визначений у файлі app-routing.module.ts
.
Для даних або логіки, які не пов'язані з конкретним видом та які ви хочете поділити між компонентами, створюється клас сервісу. Визначення класу сервісу негайно передує декоратор @Injectable()
. Декоратор надає метадані, які дозволяють іншим постачальникам бути внесеними як залежності у ваш клас. Впровадження залежностей (DI) дозволяє зберігати ваші класи компонентів легкими та ефективними. Вони не отримують дані з сервера, не перевіряють введення користувача або не реєструють безпосередньо в консоль; вони делегують такі завдання сервісам.
Налаштування карт джерел
Фреймворк Angular перетворює файли TypeScript у код JavaScript, слідуючи параметрам tsconfig.json
, а потім будує проект з конфігурацією angular.json
. Придивившись до файлу angular.json
, ми помітили опцію для увімкнення або вимкнення карт джерел. Згідно з документацією Angular, у конфігурації за замовчуванням карта джерел увімкнена для скриптів і за замовчуванням не прихована:
Загалом, файли sourcemap використовуються для налагодження з метою відображення згенерованих файлів на їх оригінальні файли. Тому не рекомендується використовувати їх у виробничому середовищі. Якщо sourcemaps увімкнені, це полегшує читабельність та допомагає у аналізі файлів, реплікуючи початковий стан проекту Angular. Однак, якщо вони вимкнені, рецензент все ще може аналізувати скомпільований файл JavaScript вручну, шукаючи антибезпечні шаблони.
Крім того, скомпільований файл JavaScript з проектом Angular можна знайти у розробницьких інструментах браузера → Джерела (або Відлагоджувач та Джерела) → [id].main.js. Залежно від увімкнених параметрів, у кінці цього файлу може бути наступний рядок //# sourceMappingURL=[id].main.js.map
або його може не бути, якщо параметр hidden встановлено на true. Тим не менш, якщо sourcemap вимкнено для scripts, тестування стає складнішим, і ми не можемо отримати файл. Крім того, sourcemap можна увімкнути під час побудови проекту, наприклад, ng build --source-map
.
Зв'язування даних
Зв'язування відноситься до процесу спілкування між компонентом та відповідним йому представленням. Воно використовується для передачі даних до та з фреймворку Angular. Дані можуть передаватися різними способами, такими як через події, інтерполяцію, властивості або за допомогою механізму двостороннього зв'язування. Крім того, дані також можуть бути спільно використані між пов'язаними компонентами (батьківсько-дочірній зв'язок) та між двома не пов'язаними компонентами за допомогою функціоналу Сервісу.
Ми можемо класифікувати зв'язування за потоком даних:
Джерело даних до цільового представлення (включає інтерполяцію, властивості, атрибути, класи та стилі); може бути застосовано за допомогою
[]
або{{}}
в шаблоні;Цільове представлення до джерела даних (включає події); може бути застосовано за допомогою
()
в шаблоні;Двостороннє; може бути застосовано за допомогою
[()]
в шаблоні.
Зв'язування може бути викликане для властивостей, подій та атрибутів, а також для будь-якого публічного члена директиви джерела:
ТИП | ЦІЛЬ | ПРИКЛАДИ |
---|---|---|
Властивість | Властивість елемента, властивість компонента, властивість директиви | <img [alt]="hero.name" [src]="heroImageUrl"> |
Подія | Подія елемента, подія компонента, подія директиви | <button type="button" (click)="onSave()">Save |
Двостороннє | Подія та властивість | <input [(ngModel)]="name"> |
Атрибут | Атрибут (виняток) | <button type="button" [attr.aria-label]="help">help |
Клас | Властивість класу | <div [class.special]="isSpecial">Special |
Стиль | Властивість стилю | <button type="button" [style.color]="isSpecial ? 'red' : 'green'"> |
Модель безпеки Angular
Дизайн Angular включає кодування або санітизацію всіх даних за замовчуванням, що ускладнює виявлення та експлуатацію вразливостей XSS в проектах Angular. Існують два відмінні сценарії обробки даних:
Інтерполяція або
{{user_input}}
- виконує кодування, яке залежить від контексту, та інтерпретує введення користувача як текст;
Результат: <script>alert(1)</script><h1>test</h1>
2. Зв'язування з властивостями, атрибутами, класами та стилями або [attribute]="user_input"
- виконує санітизацію на основі наданого контексту безпеки.
Результат: <div><h1>test</h1></div>
Існує 6 типів SecurityContext
:
None
;HTML
використовується при інтерпретації значення як HTML;STYLE
використовується при зв'язуванні CSS у властивістьstyle
;URL
використовується для URL-властивостей, наприклад<a href>
;SCRIPT
використовується для коду JavaScript;RESOURCE_URL
як URL, який завантажується та виконується як код, наприклад, у<script src>
.
Вразливості
Обхід методів довіри до безпеки
Angular вводить список методів для обходу свого процесу санітизації за замовчуванням та позначення значення, яке можна безпечно використовувати в конкретному контексті, як у наступних п'яти прикладах:
bypassSecurityTrustUrl
використовується для позначення того, що задане значення є безпечним URL-стилем:
bypassSecurityTrustResourceUrl
використовується для позначення того, що задане значення є безпечним URL-ресурсом:
bypassSecurityTrustHtml
використовується для позначення того, що задане значення є безпечним HTML. Зверніть увагу, що вставка елементівscript
в дерево DOM цим способом не призведе до виконання вкладеного коду JavaScript через те, як ці елементи додаються до дерева DOM.
bypassSecurityTrustScript
використовується для позначення того, що задане значення є безпечним JavaScript. Однак ми виявили, що його поведінка непередбачувана, оскільки ми не могли виконати код JS в шаблонах за допомогою цього методу.
bypassSecurityTrustStyle
використовується для позначення того, що задане значення є безпечним CSS. Наступний приклад ілюструє впровадження CSS:
Angular надає метод sanitize
для санітизації даних перед їх відображенням у представленнях. Цей метод використовує наданий контекст безпеки та очищує вхідні дані відповідно. Проте важливо використовувати правильний контекст безпеки для конкретних даних та контексту. Наприклад, застосування санітизатора з SecurityContext.URL
на вміст HTML не забезпечує захист від небезпечних значень HTML. У таких сценаріях неправильне використання контексту безпеки може призвести до вразливостей XSS.
Впровадження HTML
Ця уразливість виникає, коли введення користувача прив'язується до будь-якої з трьох властивостей: innerHTML
, outerHTML
або iframe
srcdoc
. При прив'язці до цих атрибутів HTML інтерпретується так, як воно є, але введення санітарно очищується за допомогою SecurityContext.HTML
. Таким чином, впровадження HTML можливе, але відсутній міжсайтовий скриптинг (XSS).
Приклад використання innerHTML
:
Результат - <div><h1>тест</h1></div>
.
Впровадження шаблону
Відображення на клієнтській стороні (CSR)
Angular використовує шаблони для динамічної побудови сторінок. Підхід передбачає вкладення виразів шаблону для оцінки Angular всередині подвійних фігурних дужок ({{}}
). Таким чином, фреймворк пропонує додатковий функціонал. Наприклад, шаблон типу {{1+1}}
відобразиться як 2.
Зазвичай Angular екранує введення користувача, яке може бути сплутане з виразами шаблону (наприклад, символи, такі як `< > ' " ``). Це означає, що для обхідної цієї обмеження потрібні додаткові кроки, такі як використання функцій, які генерують об'єкти рядка JavaScript, щоб уникнути використання заборонених символів. Однак для досягнення цього ми повинні врахувати контекст Angular, його властивості та змінні. Тому атака впровадження шаблону може виглядати наступним чином:
Як показано вище: constructor
відноситься до області властивості об'єкта constructor
, що дозволяє нам викликати конструктор String та виконувати довільний код.
Рендеринг на стороні сервера (SSR)
На відміну від CSR, який відбувається в DOM браузера, Angular Universal відповідає за SSR файлів шаблонів. Ці файли потім доставляються користувачеві. Незважаючи на це розмежування, Angular Universal застосовує ті ж механізми санітарії, які використовуються в CSR, для підвищення безпеки SSR. Уразливість внедрення шаблону в SSR можна виявити так само, як в CSR, оскільки використовується та ж мова шаблону.
Звичайно, також існує можливість введення нових уразливостей внедрення шаблону при використанні сторонніх шаблонних движків, таких як Pug та Handlebars.
XSS
Інтерфейси DOM
Як вже зазначалося, ми можемо безпосередньо отримати доступ до DOM, використовуючи інтерфейс Document. Якщо вхідні дані користувача не перевіряються заздалегідь, це може призвести до уразливостей внедрення скриптів (XSS).
Ми використовували методи document.write()
та document.createElement()
у наведених нижче прикладах:
Класи Angular
Є деякі класи, які можна використовувати для роботи з елементами DOM в Angular: ElementRef
, Renderer2
, Location
та Document
. Детальний опис останніх двох класів наведено в розділі Відкриті перенаправлення. Основна відмінність між першими двома полягає в тому, що API Renderer2
надає шар абстракції між елементом DOM та кодом компонента, тоді як ElementRef
просто містить посилання на елемент. Тому, згідно з документацією Angular, API ElementRef
слід використовувати лише в останньому випадку, коли потрібен прямий доступ до DOM.
ElementRef
містить властивістьnativeElement
, яку можна використовувати для маніпулювання елементами DOM. Однак неправильне використанняnativeElement
може призвести до вразливості на впровадження XSS, як показано нижче:
Незважаючи на те, що
Renderer2
надає API, яке можна безпечно використовувати навіть тоді, коли прямий доступ до вихідних елементів не підтримується, в ньому все ще є деякі вразливості безпеки. За допомогоюRenderer2
можна встановлювати атрибути для елементу HTML за допомогою методуsetAttribute()
, який не має механізмів запобігання XSS.
Для встановлення властивості елементу DOM можна використовувати метод
Renderer2.setProperty()
та спровокувати атаку XSS:
Під час нашого дослідження ми також розглянули поведінку інших методів Renderer2
, таких як setStyle()
, createComment()
та setValue()
, щодо XSS та впровадження CSS. Однак ми не змогли знайти жодних дійсних векторів атаки для цих методів через їх функціональні обмеження.
jQuery
jQuery - це швидка, компактна та функціонально багата бібліотека JavaScript, яку можна використовувати в проекті Angular для допомоги у маніпулюванні об'єктами HTML DOM. Однак, як відомо, методи цієї бібліотеки можуть бути використані для досягнення вразливості XSS. Для обговорення того, як деякі вразливі методи jQuery можуть бути використані в проектах Angular, ми додали цей підрозділ.
Метод
html()
отримує HTML-вміст першого елемента в наборі відповідних елементів або встановлює HTML-вміст кожного відповідного елемента. Однак за замовчуванням будь-який конструктор або метод jQuery, який приймає рядок HTML, може потенційно виконати код. Це може статися через впровадження тегів<script>
або використання атрибутів HTML, які виконують код, як показано в прикладі.
Метод
jQuery.parseHTML()
використовує вбудовані методи для перетворення рядка в набір вузлів DOM, які потім можуть бути вставлені в документ.
Як зазначено раніше, більшість методів jQuery, які приймають рядки HTML, будуть виконувати скрипти, які включені в HTML. Метод jQuery.parseHTML()
не виконує скрипти в розібраному HTML, якщо keepScripts
не є явно true
. Однак у більшості середовищ все ще можна виконати скрипти опосередковано; наприклад, через атрибут <img onerror>
.
Відкриті перенаправлення
Інтерфейси DOM
Згідно з документацією W3C, об'єкти window.location
та document.location
у сучасних браузерах розглядаються як псевдоніми. Тому вони мають схожу реалізацію деяких методів та властивостей, що може призвести до відкритого перенаправлення та DOM XSS з атаками схеми javascript://
, як показано нижче.
window.location.href
(таdocument.location.href
)
Канонічний спосіб отримання поточного об'єкта місцезнаходження DOM - використання window.location
. Його також можна використовувати для перенаправлення браузера на нову сторінку. Таким чином, контроль над цим об'єктом дозволяє нам використовувати вразливість відкритого перенаправлення.
Процес експлуатації ідентичний для наступних сценаріїв.
window.location.assign()
(таdocument.location.assign()
)
Цей метод призводить до завантаження та відображення документа за вказаною URL. Якщо у нас є контроль над цим методом, він може бути вразливим для атаки відкритого перенаправлення.
window.location.replace()
(таdocument.location.replace()
)
Цей метод замінює поточний ресурс на той, який вказано за URL.
Відмінність від методу assign()
полягає в тому, що після використання window.location.replace()
поточна сторінка не буде збережена в історії сесій. Однак також можливо використовувати вразливість відкритого перенаправлення, коли у нас є контроль над цим методом.
window.open()
Метод window.open()
приймає URL та завантажує ресурс, який він ідентифікує, в нову або існуючу вкладку або вікно. Контроль над цим методом також може бути можливістю спровокувати вразливість XSS або відкритого перенаправлення.
Класи Angular
Згідно з документацією Angular, Angular
Document
те саме, що і DOM-документ, що означає, що можна використовувати загальні вектори для DOM-документа для експлуатації клієнтських вразливостей в Angular. Властивості та методиDocument.location
можуть бути джерелами для успішних атак відкритого перенаправлення, як показано в прикладі:
Під час фази дослідження ми також переглянули клас Angular
Location
для вразливостей відкритого перенаправлення, але жодних дійсних векторів не було знайдено.Location
- це сервіс Angular, який додатки можуть використовувати для взаємодії з поточною URL-адресою браузера. У цьому сервісі є кілька методів для маніпулювання заданою URL-адресою -go()
,replaceState()
, таprepareExternalUrl()
. Однак ми не можемо використовувати їх для перенаправлення на зовнішній домен. Наприклад:
Результат: http://localhost:4200/http://google.com/about
Клас Angular
Router
використовується в основному для навігації в межах одного домену і не вводить додаткових вразливостей до додатку:
Результат: http://localhost:4200/https:
Наступні методи також навігують в межах області домену:
Посилання
Last updated