Если вы специалист по объектам и прототипам JavaScript, вы можете двигаться дальше и узнать больше о загрязнении прототипов с реальным примером и мерами защиты здесь.

Понимание того, что такое прототипы JavaScript (часть 1)

Загрязнение прототипа, вероятно, является знакомой категорией уязвимостей, связанных с JavaScript, в большинстве программ вознаграждения за обнаружение ошибок. Однако она не очень хорошо задокументирована, как и другие распространенные уязвимости, такие как SQLi, XSS, внедрение команд и т. д. Эта конкретная уязвимость может привести к серьезным последствиям, таким как компрометация сервера и клиента. Prototype Pollution влияет на языки, основанные на прототипах (но в первую очередь на JavaScript). Весьма вероятно, что по крайней мере один из продуктов создан с использованием JavaScript; следовательно, важно убедиться, что приложения свободны от этой уязвимости.

История загрязнения прототипа:

Эта уязвимость была обнаружена исследователями безопасности только после 2017 года и первоначально наблюдалась в Lodash, пакете NPM и этой DOS-атаке. Мы знаем, что Lodash имеет очень высокую популярность, поскольку он используется многими приложениями и, следовательно, представляет огромную угрозу.

Объекты JavaScript:

Прежде чем углубляться в загрязнение прототипов, давайте разберемся, что такое и как работают объекты JavaScript. Подобно другим языкам программирования, javascript также содержит примитивные типы данных, такие как числа, массивы, строки и, кроме того, объекты. Рассмотрим пример объекта — человека. Мы можем создать объект,

вар человек = {}

Если мы хотим добавить некоторые свойства к этому объекту,

var person = {имя: «Алекс»}

Мы можем получить доступ к этому свойству, используя один из двух способов ниже:

человек.имя

or

человек ["имя"]

Мы можем продолжать добавлять свойства к объекту «человек»,

человек.возраст = «27»

Давайте рассмотрим еще одну концепцию под названием Функции-конструкторы. Они похожи на обычные функции javascript с точки зрения синтаксиса. На рисунке ниже показано, как выглядит функция-конструктор.

Эти функции-конструкторы используются для создания новых объектов, в отличие от обычных функций, и выполняются с помощью ключевого слова «new». Это похоже на «var person = {name: name, age: age}», которое мы видели ранее.

Каждая переменная, используемая вместе с ключевым словом «this» внутри функций-конструкторов, является свойствами, которые добавляются к созданным объектам.

человек1 = новый человек («Алекс», 27);

Здесь объект person1 будет содержать два свойства — имя и возраст с соответствующими значениями.

человек2 = новый человек («Боб», 20);

Объект person2 также будет содержать те же свойства, что и person1, но значения зависят от того, что передается. Здесь имя Боб и возраст 20.

Свойства конструктора — это ссылка на функции конструктора, которые мы использовали для создания объектов. Чтобы получить доступ к функции конструктора объекта person1,

человек1.конструктор

Это вернет функцию-конструктор объекта person1.

Теперь, если мы хотим добавить больше свойств к нашему объекту person1,

Поскольку новый пол свойства создается для человека1, он неприменим для человека2.

В таких случаях на помощь приходят прототипы!

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

«пол» теперь добавлен в прототип функции-конструктора и, следовательно, теперь доступен для всех объектов (даже для вновь созданных).

Другой способ добавления новых свойств в прототип объекта показан ниже.

Новый объект person4 теперь имеет доступ к обоим свойствам — State и gender.

Прототип цепи:

Давайте посмотрим дальше на объект person4:

Помимо определенных свойств возраста и имени, у нас есть еще одно свойство под названием «[[Prototype]]».

Если мы расширим прототип, он будет содержать внутри себя как свойства пола, так и свойства состояния, как мы и определили. Мы можем получить доступ к прототипам любого объекта с помощью переменной с именем «__proto__». Поскольку объекты — person1, person2, person3 и person4 и любые объекты, созданные с помощью person, создаются из одной и той же функции-конструктора, все они имеют общие прототипы.

Мы используем «Object.getOwnPropertyNames(object)» для просмотра свойств, связанных с каждым объектом. Так как мы определили свойства gender и State непосредственно для объектов person1 и person2 соответственно, они отображаются напрямую. Но для person3 и person4, поскольку они сами по себе не обладают свойствами, они далее спускаются на уровень своего прототипа и проверяют те же свойства.

Это называется цепочкой прототипов. Так продолжается до тех пор, пока не будет найден ни один прототип. Это означает, что мы находимся на вершине цепочки прототипов, и в таком случае возвращается null.

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

Любое новое свойство можно добавить прямо в глобальный прототип. Теперь мы создадим новый объект под названием «автомобиль» и попытаемся получить доступ к этому свойству.

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

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

Спасибо за прочтение! Дайте мне знать ваши ценные комментарии, если я пропустил что-то добавить здесь :)

Хорошей охоты :)