NodeJS - __proto__ & prototype Pollution
Last updated
Last updated
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Об'єкти в JavaScript по суті є колекціями пар ключ-значення, відомими як властивості. Об'єкт можна створити за допомогою Object.create
з null
як аргументом, щоб отримати порожній об'єкт. Цей метод дозволяє створити об'єкт без будь-яких успадкованих властивостей.
Порожній об'єкт подібний до порожнього словника, представлений як {}
.
У JavaScript класи та функції тісно пов'язані, причому функції часто виконують роль конструкторів для класів. Незважаючи на відсутність нативної підтримки класів у JavaScript, конструктори можуть імітувати поведінку класів.
JavaScript дозволяє модифікацію, додавання або видалення атрибутів прототипу під час виконання. Ця гнучкість дозволяє динамічно розширювати функціональність класів.
Функції, такі як toString
і valueOf
, можуть бути змінені для зміни їх поведінки, демонструючи адаптивну природу системи прототипів JavaScript.
У програмуванні на основі прототипів властивості/методи успадковуються об'єктами від класів. Ці класи створюються шляхом додавання властивостей/методів або до екземпляра іншого класу, або до порожнього об'єкта.
Слід зазначити, що коли властивість додається до об'єкта, що служить прототипом для інших об'єктів (таких як myPersonObj
), успадковуючі об'єкти отримують доступ до цієї нової властивості. Однак ця властивість не відображається автоматично, якщо її не викликати явно.
Об'єкти JavaScript визначаються парами ключ-значення і успадковують від прототипу об'єкта JavaScript. Це означає, що зміна прототипу об'єкта може вплинути на всі об'єкти в середовищі.
Давайте використаємо інший приклад для ілюстрації:
Доступ до прототипу об'єкта можливий через:
Додаючи властивості до прототипу Object, кожен об'єкт JavaScript успадкує ці нові властивості:
Для сценарію, де використання __proto__
обмежене, модифікація прототипу функції є альтернативою:
Це впливає лише на об'єкти, створені з конструктора Vehicle
, надаючи їм властивості beep
, hasWheels
, honk
та isElectric
.
Два методи для глобального впливу на об'єкти JavaScript через забруднення прототипу включають:
Забруднення Object.prototype
безпосередньо:
Забруднення прототипу конструктора для загальновживаної структури:
Після цих операцій кожен об'єкт JavaScript може виконувати методи goodbye
та greet
.
У сценарії, де ви можете забруднити конкретний об'єкт і вам потрібно достукатися до Object.prototype
, ви можете шукати його за допомогою чогось на кшталт наступного коду:
Зверніть увагу, що оскільки ви можете забруднювати атрибути об'єктів у JS, якщо у вас є доступ до забруднення масиву, ви також можете забруднити значення масиву, доступні за індексами (зверніть увагу, що ви не можете перезаписувати значення, тому вам потрібно забруднити індекси, які якимось чином використовуються, але не записуються).
Коли генерується HTML-елемент за допомогою JS, можливо перезаписати атрибут innerHTML
, щоб він записував произвольний HTML-код. Ідея та приклад з цього написання.
Забруднення прототипу відбувається через недолік в додатку, який дозволяє перезаписувати властивості на Object.prototype
. Це означає, що оскільки більшість об'єктів отримують свої властивості з Object.prototype
Найпростіший приклад - це додати значення до невизначеного атрибута об'єкта, який буде перевірятися, наприклад:
Якщо атрибут admin
не визначений, можливо зловживати PP і встановити його в True за допомогою чогось на зразок:
Механізм, що стоїть за цим, полягає в маніпулюванні властивостями так, що якщо зловмисник контролює певні вхідні дані, він може змінити прототип усіх об'єктів у додатку. Ця маніпуляція зазвичай включає встановлення властивості __proto__
, яка в JavaScript є синонімом безпосередньої зміни прототипу об'єкта.
Умови, за яких ця атака може бути успішно виконана, як зазначено в конкретному дослідженні, включають:
Виконання рекурсивного злиття.
Визначення властивостей на основі шляху.
Клонування об'єктів.
Інші payloads:
Для отримання додаткової інформації перегляньте цю статтю У jQuery функція $ .extend
може призвести до прототипного забруднення, якщо функція глибокого копіювання використовується неправильно. Ця функція зазвичай використовується для клонування об'єктів або об'єднання властивостей з об'єкта за замовчуванням. Однак, коли вона неправильно налаштована, властивості, призначені для нового об'єкта, можуть бути призначені прототипу замість цього. Наприклад:
Ця вразливість, ідентифікована як CVE-2019–11358, ілюструє, як глибоке копіювання може ненавмисно змінити прототип, що призводить до потенційних ризиків безпеки, таких як несанкціонований доступ адміністратора, якщо такі властивості, як isAdmin
, перевіряються без належної перевірки існування.
Для отримання додаткових деталей перегляньте цю статтю
Lodash зіткнувся з подібними вразливостями забруднення прототипу (CVE-2018–3721, CVE-2019–10744). Ці проблеми були вирішені в версії 4.17.11.
Server-Side-Prototype-Pollution-Gadgets-Scanner: Розширення Burp Suite, призначене для виявлення та аналізу вразливостей забруднення прототипу на стороні сервера в веб-додатках. Цей інструмент автоматизує процес сканування запитів для виявлення потенційних проблем забруднення прототипу. Він використовує відомі гаджети - методи використання забруднення прототипу для виконання шкідливих дій - зокрема, зосереджуючись на бібліотеках Node.js.
server-side-prototype-pollution: Це розширення виявляє вразливості забруднення прототипу на стороні сервера. Воно використовує техніки, описані в забрудненні прототипу на стороні сервера.
NodeJS широко використовує абстрактні синтаксичні дерева (AST) в JavaScript для функціональностей, таких як шаблонні двигуни та TypeScript. Цей розділ досліджує вразливості, пов'язані із забрудненням прототипу в шаблонних двигунах, зокрема Handlebars і Pug.
Шаблонний двигун 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, ще один движок шаблонів, стикається з подібним ризиком забруднення прототипу. Докладну інформацію можна знайти в обговоренні AST Injection in Pug.
Приклад забруднення прототипу в Pug:
Щоб зменшити ризик забруднення прототипу, можна використовувати наведені нижче стратегії:
Незмінність об'єктів: Object.prototype
можна зробити незмінним, застосувавши Object.freeze
.
Валідація вводу: JSON-вводи повинні бути ретельно перевірені на відповідність схемі програми.
Безпечні функції злиття: Слід уникати небезпечного використання рекурсивних функцій злиття.
Об'єкти без прототипу: Об'єкти без властивостей прототипу можна створити за допомогою Object.create(null)
.
Використання Map: Замість Object
слід використовувати Map
для зберігання пар ключ-значення.
Оновлення бібліотек: Слід регулярно оновлювати бібліотеки, щоб включати патчі безпеки.
Інструменти лінтингу та статичного аналізу: Використовуйте інструменти, такі як ESLint з відповідними плагінами, для виявлення та запобігання вразливостям забруднення прототипу.
Огляди коду: Реалізуйте ретельні огляди коду, щоб виявити та усунути потенційні ризики, пов'язані із забрудненням прототипу.
Навчання безпеці: Освітіть розробників про ризики забруднення прототипу та найкращі практики написання безпечного коду.
Обережне використання бібліотек: Будьте обережні при використанні сторонніх бібліотек. Оцініть їх безпеку та перегляньте їх код, особливо ті, що маніпулюють об'єктами.
Захист під час виконання: Використовуйте механізми захисту під час виконання, такі як безпекові npm-пакети, які можуть виявляти та запобігати атакам забруднення прототипу.
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)