November 1, 2021

От Prototype Pollution к RCE на ZeroNights X

Как я встретил “Вашу маму”

История началась с того, что на очередном аудите я обнаружил уязвимость с интересным для меня тогда названием — Prototype Pollution. В целом я понимал, что эта уязвимость связана с прототипом именно в JavaScript, так как в других языках программирования я не встречал данного слова ну и самого прототипа тоже. Но что именно с ним происходит не так, и как вообще происходит загрязнение нашего прототипа, для меня оставались загадкой, которую я хотел решить.

Критический уровень уязвимости Prototype Pollution

Для себя я решил ответить на несколько основных вопросов:

  • Почему эта уязвимость с высоким рейтингом безопасности?
  • Что именно идет не так в уязвимых приложениях?
  • Можем ли мы добраться до удаленного исполнения кода?

Рейтинг риска безопасности приложений

Итак, почему эта уязвимость с высоким рейтингом риска?

Все просто, существует общая система оценки рейтинга уязвимых приложений, я использовал CVSS 3.0 версии и есть калькулятор для самостоятельной оценки риска. Сам рейтинг состоит из 8 основных параметров, сочетание которых и рассчитывает риск нашего приложения от 0.0 до 10.0, от меньшего большему риску соответственно. Так как вектор атаки у нас сетевой, сложность эксплуатации небольшая и доступность высокая, вот мы и получаем рейтинг HIGH от 7.3 и выше для некоторых весьма популярных уязвимых приложений:

Прототип в JavaScript

Давайте представим, что мы создаем пустой объект в JavaScript. Пусть будет
const test = {} При создании наш новый созданный объект уже имеет множество свойств и методов. Откуда они взялись у него? Ответ — прототип.

Объектно-ориентированные языки Java или PHP к примеру, используют классы как схемы для создания объектов. Каждый объект принадлежит классу, и классы организованы в так называемую иерархии, Родитель — Потомок. Если мы вызываем любой метод объекта, среда выполнения языка или компилятор будет искать метод в классе, к которому принадлежит объект и если он его не сможет найти, то будет искать выше в родительском классе, а затем еще выше, пока не достигнет вершины иерархии классов.

Но JavaScript другой — это объектно-ориентированный язык программирования, основанный на прототипах. Каждый объект связан с «прототипом». Когда мы вызываем метод, например test.doSomething(), JavaScript сначала будет проверять, определяли ли мы его сами явно для нашего объекта и если нет, то пойдет искать его в прототипе.

Прототип есть у всех объектов, даже пустых

Как происходит загрязнение прототипа?

Загрязнение прототипа — это инъекционная атака. При эксплуатации злоумышленник может контролировать значения свойств объекта по умолчанию. То есть, это позволяет злоумышленнику изменять логику приложения. Суть в том, что если мы изменяем свойство в прототипе, который общий для двух или более объектов, то все объекты в итоге получат измененное нами свойство!

Это важно понимать, так как большинство объектов по умолчанию используют один и тот же прототип, поэтому, если мы изменим прототип только одного из объектов, мы сможем изменить поведение всех объектов!

Загрязнение прототипа пакета flat v5.0.0

Дотянуться до RCE

В последнее время появляется все больше статей про Prototype Pollution в связке с XSS. Так как JavaScript в основном используется на стороне клиента, то и вектор эксплуатации видится нам, как возможность дотянуться до XSS, но это не совсем всё что можно сделать.

Мы поговорим о другом векторе, а именно, возможно ли довести вектор атаки до эксплуатации на стороне сервера. Для понимания эксплуатации уязвимости на серверной стороне нужно знать две вещи:

  • место, где присутствует уязвимость Prototype Pollution
  • и как, или посредством чего, уязвимость может влиять на серверную логику приложения.

Если у нас на сервере стоит NodeJS, то нам на помощь приходит AST с его возможностью обрабатывать и исполнять код на сторону сервера.

AST (Abstract Syntax Tree) — абстрактное синтаксическое дерево. Это особое представление (можно представить в виде описательного JSON объекта), с которым было бы удобно программно обрабатывать код. Зачастую используемая в шаблонизаторах и при компиляции TypeScript. Для более углубленного понимания работы AST рекомендую почитать эту статью.

Если мы имеем дело с одним из шаблонизаторов, например PUG, то программная обработка кода его выглядеть будет как на схеме.

Схема корректной обработки кода в шаблонизаторе PUG

Если мы нашли уязвимости Prototype Pollution, то можем воспользоваться AST, заставив исполнить наш произвольный код, направив его в процессы parser или compiler. Шаблонизаторы Handlebars и Pug удачно подходят для этой цели.

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

Участок кода пакета шаблонизатора PUG где исполняется код

Конкурс на ZeroNights X

25 августа 2021 в Санкт-Петербурге прошла десятая конференция по информационной безопасности ZeroNights. Это хакерская конференция c атмосферной обстановкой и большим сообществом, конкурсы для которой я готовил неоднократно.

В этот раз конкурс назвали “Hack to be Hired”. Этим названием мы хотели подчеркнуть важность навыков в сфере информационной безопасности при приеме на работу в различные ИТ-компании.

Идея конкурса родилась из популярного мема.

Чтобы усложнить задание, мы сделали все вакансии компании неактивными. Так, злоумышленнику предстоит взломать сайт компании, открыть вакансию, которая пришлась ему по душе, затем ответить на нее и принять свое же приглашение.

Сценарий конкурса

  • участник изучает сайт компании
  • собирает всю необходимую информацию
  • взламывает административную панель
  • активирует выбранную им вакансию
  • эксплуатирует найденные уязвимости и получает RCE на сервере
  • получив RCE можно перевести свое резюме в статус одобренной

Следовательно, если участник пригласил себя на собеседование – победа!
Последний флаг успешно получен, и поставленная задача выполнена.

Итоги

Сценарий проверили и запустили на нашей образовательной платформе. Благодаря персонажам и игровым механикам конкурс получился интерактивным и занимательным.

Тизер для тех, кто хочет пройти ее: лабораторная работа скоро будет включена в курс JavaScript на платформе Академии Digital Security.

Спасибо всем, кто дочитал до конца!

Список использованных материалов: