Angular
The Checklist
Checklist from here.
What is Angular
Angular є потужним та відкритим фреймворком для фронтенду, який підтримується Google. Він використовує TypeScript для покращення читабельності коду та налагодження. Завдяки сильним механізмам безпеки, Angular запобігає поширеним вразливостям на стороні клієнта, таким як XSS та відкриті редиректи. Його також можна використовувати на стороні сервера, що робить питання безпеки важливими з обох сторін.
Framework architecture
Щоб краще зрозуміти основи Angular, давайте розглянемо його основні концепції.
Звичайний проект Angular зазвичай виглядає так:
Згідно з документацією, кожен Angular додаток має принаймні один компонент, кореневий компонент (AppComponent
), який з'єднує ієрархію компонентів з DOM. Кожен компонент визначає клас, який містить дані та логіку додатку, і асоційований з HTML шаблоном, який визначає вигляд, що має бути відображений у цільовому середовищі. Декоратор @Component()
ідентифікує клас безпосередньо під ним як компонент і надає шаблон та відповідну специфічну метадані компонента. AppComponent
визначено у файлі app.component.ts
.
Angular NgModules оголошують контекст компіляції для набору компонентів, який присвячений домену додатку, робочому процесу або тісно пов'язаному набору можливостей. Кожен Angular додаток має кореневий модуль, звичайно названий AppModule
, який надає механізм завантаження, що запускає додаток. Додаток зазвичай містить багато функціональних модулів. AppModule
визначено у файлі app.module.ts
.
NgModule Angular Router
надає сервіс, який дозволяє вам визначити навігаційний шлях серед різних станів додатку та ієрархій виглядів у вашому додатку. RouterModule
визначено у файлі app-routing.module.ts
.
Для даних або логіки, які не пов'язані з конкретним виглядом і які ви хочете поділитися між компонентами, ви створюєте клас сервісу. Визначення класу сервісу безпосередньо передує декоратору @Injectable()
. Декоратор надає метадані, які дозволяють іншим провайдерам бути впровадженими як залежності у ваш клас. Впровадження залежностей (DI) дозволяє вам зберігати ваші класи компонентів стрункими та ефективними. Вони не отримують дані з сервера, не перевіряють введення користувача і не ведуть безпосередній лог до консолі; вони делегують такі завдання сервісам.
Налаштування sourcemap
Фреймворк Angular перекладає файли TypeScript у JavaScript код, дотримуючись параметрів tsconfig.json
, а потім будує проект з конфігурацією angular.json
. Розглядаючи файл angular.json
, ми спостерігали опцію для увімкнення або вимкнення sourcemap. Згідно з документацією Angular, за замовчуванням конфігурація має файл sourcemap, увімкнений для скриптів, і за замовчуванням не прихований:
Загалом, файли sourcemap використовуються для налагодження, оскільки вони відображають згенеровані файли на їх оригінальні файли. Тому не рекомендується використовувати їх у виробничому середовищі. Якщо sourcemaps увімкнено, це покращує читабельність і допомагає в аналізі файлів, відтворюючи оригінальний стан проекту Angular. Однак, якщо вони вимкнені, рецензент все ще може вручну проаналізувати скомпільований JavaScript файл, шукаючи антибезпекові шаблони.
Крім того, скомпільований JavaScript файл з проектом Angular можна знайти в інструментах розробника браузера → Sources (або Debugger і Sources) → [id].main.js. Залежно від увімкнених опцій, цей файл може містити наступний рядок в кінці //# sourceMappingURL=[id].main.js.map
або може не містити, якщо опція hidden встановлена на true. Проте, якщо sourcemap вимкнено для scripts, тестування стає більш складним, і ми не можемо отримати файл. Крім того, sourcemap може бути увімкнено під час збірки проекту, наприклад, ng build --source-map
.
Прив'язка даних
Прив'язка відноситься до процесу комунікації між компонентом і відповідним виглядом. Вона використовується для передачі даних до та з фреймворку Angular. Дані можуть передаватися різними способами, такими як через події, інтерполяцію, властивості або через механізм двосторонньої прив'язки. Крім того, дані також можуть бути спільними між пов'язаними компонентами (відношення батька і дитини) та між двома несумісними компонентами за допомогою функції Service.
Ми можемо класифікувати прив'язку за потоком даних:
Джерело даних до цільового вигляду (включає інтерполяцію, властивості, атрибути, класи та стилі); може бути застосовано за допомогою
[]
або{{}}
у шаблоні;Цільовий вигляд до джерела даних (включає події); може бути застосовано за допомогою
()
у шаблоні;Двостороння; може бути застосовано за допомогою
[()]
у шаблоні.
Прив'язка може бути викликана на властивостях, подіях і атрибутах, а також на будь-якому публічному члені директиви джерела:
Property
Властивість елемента, Властивість компонента, Властивість директиви
<img [alt]="hero.name" [src]="heroImageUrl">
Event
Подія елемента, Подія компонента, Подія директиви
<button type="button" (click)="onSave()">Save
Two-way
Подія та властивість
<input [(ngModel)]="name">
Attribute
Атрибут (виняток)
<button type="button" [attr.aria-label]="help">help
Class
Властивість класу
<div [class.special]="isSpecial">Special
Style
Властивість стилю
<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>test</h1></div>
.
Впровадження шаблонів
Візуалізація на стороні клієнта (CSR)
Angular використовує шаблони для динамічного створення сторінок. Цей підхід передбачає обгортання виразів шаблону для оцінки Angular у подвійні фігурні дужки ({{}}
). Таким чином, фреймворк пропонує додаткову функціональність. Наприклад, шаблон {{1+1}}
відобразиться як 2.
Зазвичай Angular екранує введення користувача, яке може бути сплутане з виразами шаблону (наприклад, символи такі як `< > ' " ``). Це означає, що для обходу цього обмеження потрібні додаткові кроки, такі як використання функцій, які генерують об'єкти рядків JavaScript, щоб уникнути використання заборонених символів. Однак, щоб досягти цього, ми повинні врахувати контекст Angular, його властивості та змінні. Тому атака впровадження шаблонів може виглядати наступним чином:
Як показано вище: constructor
посилається на область дії властивості Object 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
. Детальний опис останніх двох класів наведено в розділі Open redirects. Головна різниця між першими двома полягає в тому, що 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 вузлів, які потім можуть бути вставлені в документ.
Як вже згадувалося, більшість API jQuery, які приймають HTML рядки, виконуватимуть скрипти, які включені в HTML. Метод jQuery.parseHTML()
не виконує скрипти в розібраному HTML, якщо keepScripts
явно не встановлено в true
. Однак у більшості середовищ все ще можливо виконати скрипти непрямо; наприклад, через атрибут <img onerror>
.
Open redirects
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