NodeJS - __proto__ & prototype Pollution
Об'єкти в JavaScript
Об'єкти в JavaScript суттєво є колекціями пар ключ-значення, відомих як властивості. Об'єкт можна створити за допомогою Object.create
з null
як аргументом, щоб створити порожній об'єкт. Цей метод дозволяє створювати об'єкт без успадкованих властивостей.
Порожній об'єкт подібний до порожнього словника, який представлений як {}
.
Функції та Класи в JavaScript
У JavaScript класи та функції тісно пов'язані, причому функції часто виступають у ролі конструкторів для класів. Незважаючи на відсутність вбудованої підтримки класів у JavaScript, конструктори можуть емулювати поведінку класу.
Прототипи в JavaScript
JavaScript дозволяє змінювати, додавати або видаляти атрибути прототипу під час виконання. Ця гнучкість дозволяє динамічно розширювати функціонал класу.
Функції, такі як toString
та valueOf
, можуть бути змінені для зміни їхньої поведінки, демонструючи адаптивну природу прототипної системи JavaScript.
Наслідування
У прототипному програмуванні властивості/методи успадковуються об'єктами від класів. Ці класи створюються шляхом додавання властивостей/методів або до екземпляра іншого класу, або до порожнього об'єкта.
Слід зауважити, що коли властивість додається до об'єкта, який служить прототипом для інших об'єктів (наприклад, myPersonObj
), успадковані об'єкти отримують доступ до цієї нової властивості. Однак ця властивість не відображається автоматично, якщо її не викликати явно.
Забруднення __proto__
Дослідження забруднення прототипу в JavaScript
Об'єкти JavaScript визначаються пар ключ-значення та успадковуються від прототипу об'єкта JavaScript. Це означає, що зміна прототипу Object може вплинути на всі об'єкти в середовищі.
Давайте скористаємося іншим прикладом для пояснення:
Доступ до прототипу об'єкта можливий через:
Додавши властивості до прототипу Object, кожен об'єкт JavaScript успадкує ці нові властивості:
забруднення прототипу
Для сценарію, де використання __proto__
обмежено, зміна прототипу функції є альтернативою:
Це впливає лише на об'єкти, створені з конструктора Vehicle
, надаючи їм властивості beep
, hasWheels
, honk
та isElectric
.
Два методи глобального впливу на об'єкти JavaScript через забруднення прототипу включають:
Забруднення прямо
Object.prototype
:
Забруднення прототипу конструктора для широко використовуваної структури:
Після цих операцій кожен об'єкт JavaScript може виконувати методи goodbye
та greet
.
Забруднення інших об'єктів
Від класу до Object.prototype
У сценарії, де ви можете забруднити конкретний об'єкт і вам потрібно дістатися до Object.prototype
, ви можете знайти його за допомогою наступного коду:
Забруднення елементів масиву
Зверніть увагу, що так як ви можете забруднювати атрибути об'єктів в JS, якщо у вас є доступ до забруднення масиву, ви також можете забруднювати значення масиву, доступні за індексами (зверніть увагу, що ви не можете перезаписати значення, тому вам потрібно забруднювати індекси, які якось використовуються, але не записуються).
Забруднення елементів Html
При генерації елемента HTML через JS можна перезаписати атрибут innerHTML
, щоб він записав довільний HTML-код. Ідея та приклад з цього опису.
Приклади
Базовий Приклад
Забруднення прототипу відбувається через вразливість програми, яка дозволяє перезаписувати властивості в Object.prototype
. Це означає, що оскільки більшість об'єктів походять від Object.prototype
Найпростіший приклад - додати значення до невизначеного атрибуту об'єкта, який буде перевірений, наприклад:
Якщо атрибут admin
не визначено, можна скористатися PP та встановити його на True за допомогою наступного:
Механізм полягає в маніпулюванні властивостями так, що якщо зловмисник має контроль над певними вхідними даними, він може змінити прототип всіх об'єктів у додатку. Ця маніпуляція зазвичай включає встановлення властивості __proto__
, яка в JavaScript є синонімом прямого змінення прототипу об'єкта.
Умови, за яких цей атака може бути успішно виконана, як описано в конкретному дослідженні, включають:
Виконання рекурсивного злиття.
Визначення властивостей на основі шляху.
Клонування об'єктів.
Перевизначення функції
Прото-забруднення до RCE
pagePrototype Pollution to RCEПрото-забруднення на клієнтській стороні до XSS
pageClient Side Prototype PollutionCVE-2019–11358: Атака прототипного забруднення через jQuery $ .extend
Для отримання додаткових відомостей перегляньте цю статтю У jQuery функція $ .extend
може призвести до прототипного забруднення, якщо функцію глибокого копіювання використовується неправильно. Ця функція часто використовується для клонування об'єктів або об'єднання властивостей з об'єкта за замовчуванням. Однак, при неправильній конфігурації властивості, призначені для нового об'єкта, можуть бути призначені прототипу замість цього. Наприклад:
Ця вразливість, ідентифікована як CVE-2019–11358, показує, як глибока копія може ненавмисно змінити прототип, що призводить до потенційних загроз безпеці, таких як несанкціонований доступ адміністратора, якщо властивості, наприклад isAdmin
, перевіряються без належної перевірки існування.
CVE-2018–3721, CVE-2019–10744: Атака забруднення прототипу через lodash
Для отримання додаткових відомостей перегляньте цю статтю
Lodash стикався з подібними вразливостями забруднення прототипу (CVE-2018–3721, CVE-2019–10744). Ці проблеми були вирішені у версії 4.17.11.
Інший посібник з CVE
Інструменти для виявлення забруднення прототипу
Server-Side-Prototype-Pollution-Gadgets-Scanner: Розширення Burp Suite, призначене для виявлення та аналізу вразливостей забруднення прототипу на серверному боці у веб-додатках. Цей інструмент автоматизує процес сканування запитів для виявлення потенційних проблем забруднення прототипу. Він використовує відомі гаджети - методи використання забруднення прототипу для виконання шкідливих дій - зокрема зосереджуючись на бібліотеках Node.js.
server-side-prototype-pollution: Це розширення ідентифікує вразливості забруднення прототипу на серверному боці. Воно використовує техніки, описані в забрудненні прототипу на серверному боці.
Забруднення прототипу AST в NodeJS
NodeJS широко використовує Абстрактні Синтаксичні Дерева (AST) в JavaScript для функцій, таких як шаблонні двигуни та TypeScript. Цей розділ досліджує вразливості, пов'язані з забрудненням прототипу в шаблонних двигунах, зокрема Handlebars та Pug.
Аналіз вразливості Handlebars
Шаблонний двигун Handlebars піддається атакам забруднення прототипу. Ця вразливість виникає з конкретних функцій у файлі javascript-compiler.js
. Функція appendContent
, наприклад, конкатенує pendingContent
, якщо воно присутнє, тоді як функція pushSource
скидає pendingContent
на undefined
після додавання джерела.
Процес експлуатації
Експлуатація використовує AST (Абстрактне Синтаксичне Дерево), створене Handlebars, слідуючи цими кроками:
Маніпулювання Парсером: Спочатку парсер, через вузол
NumberLiteral
, забезпечує, що значення є числовими. Забруднення прототипу може обійти це, дозволяючи вставляти нечислові рядки.Обробка Компілятором: Компілятор може обробляти об'єкт AST або рядковий шаблон. Якщо
input.type
дорівнюєProgram
, вхід вважається попередньо розібраним, що може бути експлуатовано.Впровадження Коду: Шляхом маніпулювання
Object.prototype
можна впровадити довільний код у функцію шаблону, що може призвести до виконання віддаленого коду.
Приклад, що демонструє експлуатацію вразливості Handlebars:
Цей код показує, як зловмисник може впровадити довільний код у шаблон Handlebars.
Зовнішнє посилання: Проблема, пов'язана з забрудненням прототипу, була виявлена в бібліотеці 'flat', як описано тут: Проблема на GitHub.
Зовнішнє посилання: Проблема, пов'язана з забрудненням прототипу в бібліотеці 'flat'
Приклад експлойтування забруднення прототипу в Python:
Уразливість Pug
Pug, ще один шаблонний двигун, стикається з аналогічним ризиком забруднення прототипу. Детальна інформація доступна у обговоренні на AST Injection in Pug.
Приклад забруднення прототипу в Pug:
Запобіжні заходи
Для зменшення ризику забруднення прототипу можна використовувати такі стратегії:
Незмінність об'єктів:
Object.prototype
можна зробити незмінним, застосувавшиObject.freeze
.Валідація введення: JSON-введення повинно бути ретельно перевірене на відповідність схемі додатка.
Безпечні функції злиття: Небезпечне використання рекурсивних функцій злиття слід уникати.
Об'єкти без прототипів: Об'єкти без властивостей прототипу можна створити за допомогою
Object.create(null)
.Використання Map: Замість
Object
слід використовуватиMap
для зберігання пар ключ-значення.Оновлення бібліотек: Патчі безпеки можна внести, регулярно оновлюючи бібліотеки.
Інструменти лінтера та статичного аналізу: Використовуйте інструменти, такі як ESLint з відповідними плагінами, для виявлення та запобігання вразливостям забруднення прототипу.
Перегляди коду: Здійснюйте ретельні перегляди коду для виявлення та усунення потенційних ризиків, пов'язаних із забрудненням прототипу.
Навчання з безпеки: Навчайте розробників про ризики забруднення прототипу та найкращі практики написання безпечного коду.
Обережне використання бібліотек: Будьте обережні при використанні сторонніх бібліотек. Оцінюйте їх безпековий стан та переглядайте їх код, особливо ті, що маніпулюють об'єктами.
Захист під час виконання: Використовуйте механізми захисту під час виконання, такі як використання пакетів npm, спрямованих на безпеку, які можуть виявляти та запобігати атакам забруднення прототипу.
Посилання
Last updated