Skip to content
KitploitKITPLOIT
ИнструментыБлог
Отправить
ИнструментыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
proposal-symbol-proto — TC39 proposal for mitigating prototype pollution | Kitploit
Инструменты/GitHubGitHub/tc39/proposal-symbol-proto
Vulnerability AnalysisWeb SecurityPapers & ResearchLearning & Education
GitHubtc39/proposal-symbol-proto

proposal-symbol-proto

TC39 proposal for mitigating prototype pollution

Репозиторий
5322 лет назадПроверено Kitploit

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

Смягчение Prototype Pollution / Symbol.proto

Авторы: Santiago Díaz (Google)

Куратор: Shu-yu Guo (Google)

Стадия: 1

Содержание

  • Описание проблемы
    • Жуткое дальнодействие
    • Атаки только данными
  • Проблемы с freeze, seal и preventExtensions
    • Ошибка override
    • Грубая гранулярность
    • Точки заморозки
    • Типы приложений
  • Предлагаемое решение
    • Предоставление reflection API
    • Опциональная функция
      • Автоматический рефакторинг
    • Что означает delete?
  • Несовместимые кодовые базы
  • Приложение
    • А как насчет constructor pollution?
    • Вычисляемый доступ в минифицированном JS
    • Примеры уязвимостей

tl;dr

Это предложение направлено на смягчение уязвимости уровня языка, известной как prototype pollution, с помощью механизма, дополняющего примитивы заморозки, и механизма, делающего с ним совместимым большинство кодовых баз. В нём описывается opt-in функция, которая делает прототипы доступными только через reflection API. Благодаря этому выражение obj[key] больше не может получить доступ к прототипам. Кодовые базы, совместимые с этой функцией, становятся более осознанными в том, как они используют прототипы.

Описание проблемы

Жуткое дальнодействие

Уязвимости PP позволяют атакующим манипулировать объектами, которыми они не управляют или к которым у них нет доступа во время выполнения. Этот примитив «жуткого дальнодействия» может использоваться для изменения формы других объектов и переопределения их свойств, тем самым отравляя объекты в рантайме.

Отравленные объекты разрушают базовые предположения кода, который в противном случае был бы безопасным/корректным, и могут приводить к произвольному выполнению кода и широкому спектру других проблем безопасности в JS-кодовых базах. Ошибки prototype pollution часто проявляются в веб-приложениях, но также затрагивают и не-веб JS-рантаймы.

Свойства объектов в JS доступны для записи любому коду, который может на них ссылаться. В частности, если множество объектов полагается на общее свойство, любой из них может вносить изменения во все остальные.

Атаки только данными

Особое свойство PP состоит в том, что это data-only атака, позволяющая достичь выполнения кода чисто через данные. Например, рассмотрим следующий уязвимый код и соответствующий эксплойт:

root@kitploit:~
// source is attacker-controlled
function merge(target, source) {
  for (let key in source) {
    if (typeof source[key] === 'object')  {
      if(target[key] === undefined) {
        target[key] = {};
      }
      target[key] = merge(target[key], source[key]);
    } else {
      target[key] = source[key];
    }
  }
  return target;
}

// User input comes as a string
const userSuppliedObj = JSON.parse('{"__proto__": {"polluted": true}}');
// Trigger prototype pollution
merge({}, userSuppliedObj);
// Create a brand new object
const newObj = {};
// Has polluted property
console.log(newObj.polluted); // true

Обратите внимание, что эксплойт способен отравить создание новых объектов, не внедряя никакого постороннего кода.

Из-за этого особого свойства современные средства смягчения проблем с выполнением кода — такие как Content Security Policy или Trusted Types — не способны защитить от PP, поскольку они сосредоточены на обеспечении происхождения кода.

Примечание: data-only атаки актуальны в ситуациях, когда код, выполняющийся на VM, является доверенным, а произвольное выполнение кода имеет последствия для безопасности.

Проблемы с freeze, seal и preventExtensions

Существующие примитивы заморозки страдают от серьёзных проблем дизайна, из-за которых их вряд ли широко примут. Они могут быть полезны экспертам, но не подходят для применения большинством разработчиков, которые обоснованно ожидают, что прототипы будут изменяемыми:

Ошибка override

Freeze API страдают от ошибки override и других несогласованностей, которые вносят баги в существующие кодовые базы, заставляя их выбрасывать исключения или, что хуже, молча выходить из строя в нестрогом режиме. Предыдущее исследование ошибки override показало, что ошибка override срабатывает примерно в 10% кодовых баз в строгом режиме и в 20% в нестрогом режиме. Вскоре после этого исследование было свёрнуто.

Грубая гранулярность

Freeze API возлагают на разработчиков тяжёлую ответственность за знание того, какие прототипы следует замораживать для поддержания безопасной кодовой базы, предполагая, что разработчики являются экспертами по безопасности. Эти API описывают что, но не как в безопасности. Замораживания Object, безусловно, недостаточно, поскольку многие эксплойты злоупотребляют Array. А как насчёт Error, Date, Reflect или Proxy? Или будущих встроенных типов? Freeze API не дают ответов на эти вопросы.

Точки заморозки

Freeze API предполагают стабильную точку заморозки: фиксированный момент во время выполнения, когда прототипы устоялись и их можно заморозить. На практике эта точка нестабильна и со временем меняется в активно разрабатываемых кодовых базах. Хотя сегодня во многих приложениях можно найти такую точку, добавление новых зависимостей, полифиллов, изменение структуры кода и такие мощные функции, как горячая замена и инструменты разработчика, превращают точки заморозки в движущуюся цель.

Типы приложений

Freeze API не могут защитить всю цепочку прототипов. В JS объекты могут быть добавлены в цепочку прототипов или удалены из неё в любой момент времени. Чтобы защитить всю цепочку, нужно всегда помнить о заморозке объектов, добавляемых в цепочку, — это процесс, подверженный ошибкам. Когда они удаляются из цепочки, их уже нельзя разморозить.

Предлагаемое решение

В двух словах: функция, которая открывает прототипы только через reflection API. Если бы прототипы не были доступны через такие свойства, как __proto__ или prototype, они не были бы подвержены data-only проблемам.

Это лучше понять на примере: выражение obj[one][two] = value уязвимо к PP через obj.__proto__.polluted. Если удалить свойство Object.prototype.__proto__, то то же выражение больше не уязвимо, поскольку не может использовать единственный другой способ добраться до прототипов, а именно obj.constructor.prototype.polluted. Обратите внимание, что прототип нельзя удалить.

Это предложение может быть реализовано путём предоставления reflection API и создания новой опциональной функции инкапсуляции, которая удаляет свойства прототипов. Ниже приводится описание каждого шага.

Предоставление reflection API

__proto__ — это устаревшее имя свойства, которое можно удалить, но внутренний слот за ним по-прежнему можно читать через Object/Reflect.getPrototypeOf и записывать через Object/Reflect.setPrototypeOf; это просто продолжит делать свойство доступным для уже выполняющегося кода.

Мы предлагаем создать новые API для prototype, например getClassPrototypeOf и setClassPrototypeOf, которые позволят удалить это имя свойства, никак не меняя того, как это особое свойство работает и поддерживает VM.

Reflection API можно реализовать с помощью полифиллов, что позволяет укреплённым кодовым базам работать во всех браузерах, включая старые версии.

Опциональная функция

Новая опциональная «функция инкапсуляции», при которой для функций-геттеров и функций-сеттеров слотов прототипов не создаются имена свойств; теперь это возможно, поскольку вместо ссылок на эти свойства можно использовать reflection API.

Функция включается с помощью внеполосного флага:

  • В браузерных контекстах — через HTTP-заголовок, например X-Encapsulate-Prototype: true
  • В других контекстах — через флаг, например --encapsulate-prototype

Когда инкапсуляция отключена, прототипы доступны как через свойства, так и через reflection API.

Когда инкапсуляция включена, прототипы доступны только через reflection API, поскольку удалены и __proto__, и prototype.

Инкапсуляция также включает следующую функцию автоматического рефакторинга:

Автоматический рефакторинг

Когда инкапсуляция включена, JS-движки при загрузке нового исходного кода добавляют дополнительный шаг в фазу разбора, который регистрирует все обращения через точечную нотацию к свойствам прототипов так, как если бы это были вызовы соответствующих reflection API. Этот шаг может быть реализован эффективно и позволяет кодовым базам с сторонними, транзитивными или динамически загружаемыми зависимостями быть совместимыми с инкапсуляцией.

В будущем это изменение подготовит почву для пометки prototype как устаревшего.

Что означает delete?

Свойства прототипов при включённой инкапсуляции могут быть просто undefined, но они могут и выбрасывать ошибку при попытках чтения/записи. Это означало бы быстрый и громкий отказ и позволило бы тестировать миграцию на reflection API/инкапсуляцию.

Это подразумевает сделать геттеры и сеттеры __proto__ и prototype условными в зависимости от инкапсуляции, используя хук хоста, аналогично тому, как функция eval выбрасывает исключение при Content Security Policy.

Несовместимые кодовые базы

Код, который полагается на вычисляемый доступ к свойствам для обращения к прототипам, несовместим ни с инкапсуляцией, ни с автоматическим рефакторингом. Его необходимо отрефакторить, чтобы явно обращаться к прототипам при их использовании. Такой рефакторинг фактически заставляет код выражать намерение, что делает опасные паттерны видимыми для статического анализа. На практике кодовые базы с такой характеристикой — это обычно reflection-фреймворки, инструменты отладки и другие сценарии активного использования reflection, которые, скорее всего, осознают, как они используют прототипы.

Кодовые базы, использующие слово prototype для определения пользовательских свойств, несовместимы. Такие кодовые базы можно сделать совместимыми с инкапсуляцией, если это свойство всегда устанавливается/читается через скобочную нотацию. Исторически, согласно запросам HTTP Archive, существует небольшой процент кодовых баз, несовместимых по этой причине.

Приложение

А как насчет constructor pollution?

Некоторые изменения свойства constructor также могут обладать эффектом «жуткого дальнодействия». В ходе нашего исследования мы не нашли практических уязвимостей, затронутых этим.

Планка для успешности этой атаки значительно высока: как и в PP, нужно найти приложение с гаджетами, позволяющими и записывать, и читать произвольные свойства. Но в constructor pollution читающий гаджет должен читать из constructor.polluted, а не из polluted. Это резко сокращает число полезных гаджетов.

Вычисляемый доступ в минифицированном JS

Некоторый минифицированный JS может быть несовместим с режимом инкапсуляции, поскольку статический доступ к свойствам может быть минифицирован в вычисляемый доступ. Мы обратились к HTTP Archive, чтобы получить оценку этого на практике. Следующая таблица показывает, что страницы с таким поведением стабильно ниже 1% в течение последних 12 месяцев для всех страниц, просканированных десктопным браузером:

Примеры уязвимостей

Google наблюдает восходящий тренд в количестве багов, поступающих в нашу программу вознаграждения за уязвимости: 1 в 2020 году, 3 в 2021 и 5 на данный момент в 2022. Мы также выявили ещё несколько в ходе наших внутренних исследований.

Примеры уязвимостей включают:

  1. В вебе: Несколько проблем XSS в сервисах, которые должны были быть защищены, поскольку они используют Strict CSP. А также широкий спектр известных уязвимых библиотек.
  2. На десктопе: Баг в десктопном приложении Google, в котором пользователям мог быть передан вредоносный JSON-объект, способный привести к утечке локальных файлов из-за уязвимости pollution. (В настоящее время не публичное, раскрытие TBD.)
  3. В функциях безопасности: Множественные обходы санитайзеров, включая Sanitizer API Chrome, DOMPurify и санитайзер Closure.
  4. В браузере: Побег из песочницы Firefox, ведущий к удалённому выполнению кода.
  5. В NodeJS: Обнаружено несколько RCE.

Мы ожидаем, что число уязвимых приложений будет расти по мере развёртывания JavaScript-приложений в большем количестве сред (например, Electron, Cloudflare Workers и т.д.). Поэтому для смягчения атак во всех средах требуется решение на уровне языка.

Скачать инструмент
ТаблицаДокументы, динамически обращающиеся к __proto__ или constructorВсего просканировано документовДоля
2023_03_01_desktop5,407,936609,469,4580.89%
2023_02_01_desktop4,842,383549,089,7080.88%
2023_01_01_desktop5,283,826589,519,1600.90%
2022_12_01_desktop5,161,471577,073,8830.89%
2022_11_01_desktop5,023,169561,726,2390.89%
2022_10_01_desktop4,393,377476,880,6240.92%
2022_09_01_desktop4,239,257466,278,7620.91%
2022_08_01_desktop4,259,814463,784,0470.92%
2022_07_01_desktop3,011,137339,468,6150.89%
2022_06_01_desktop2,301,317257,501,2220.89%
2022_04_01_desktop2,368,577263,144,6570.90%
2022_03_01_desktop2,319,518259,249,0130.89%