Перейти к содержимому
← Каталог nodejs SSTI

Prototype Pollution: загрязнение Object.prototype приводит к DoS публичных эндпоинтов

Express-эндпоинт POST /profile/settings делает рекурсивный merge JSON-объекта в per-user настройки без фильтрации __proto__. Атакующий загрязняет Object.prototype, после чего hot-path обработчик /catalog падает с 500 на каждом запросе — Denial of Service. Endpoint /api/incident-response регистрирует инцидент и выдаёт флаг.

hardnodejsPro
Задача
# Prototype Pollution: DoS публичного каталога В этой лабораторной работе вы найдёте классическую уязвимость **Prototype Pollution** в Express-сервисе SecureShop и используете её как **DoS-gadget**, чтобы положить публичный каталог товаров на колени. Уязвимое место — endpoint обновления пользовательских настроек, который рекурсивно мёрджит произвольный JSON в in-memory дерево настроек без фильтрации зарезервированных ключей `__proto__`, `constructor`, `prototype`. ## Поверхность атаки Сервис SecureShop — стандартный e-commerce backend на Express + better-sqlite3. После логина пользователь может тонко настроить свой профиль через JSON API: - **POST `/profile/settings`** — принимает JSON-объект с настройками пользователя (тема, нотификации, размер страницы каталога) и сохраняет их в per-user runtime cache. - **GET `/catalog`** — публичный hot-path для всех посетителей: отрисовывает товары и формирует строку тегов для каждой карточки. Внутри renderer'а используется паттерн `for...in` по объекту тегов товара. - **GET `/api/incident-response`** — операторский диагностический endpoint. Снимает срез `Object.prototype` при старте сервиса и сообщает любые «лишние» собственные ключи, появившиеся в рантайме. При обнаружении инцидента отдаёт flag-токен для post-mortem отчёта. ## Логика уязвимости 1. На уровне приложения есть единый поток JavaScript-объектов: каталог, теги, настройки, сессии — всё это плоские POJO. 2. `Object.prototype` — общий предок всех POJO. Любое свойство, выставленное на нём, становится **inherited enumerable** ключом для каждого объекта в процессе. 3. `for...in` обходит и собственные, и наследованные перечисляемые ключи. Если злоумышленник добавит на `Object.prototype` ключ с примитивом, любой `for...in` в hot-path начнёт «спотыкаться» на нём. Когда вы загружаете каталог, рендерер вызывает `tags[tag].toUpperCase()` для каждого тега. Если значение тега — примитив (например, число `1`), `.toUpperCase()` бросает `TypeError`, обработчик возвращает HTTP 500, и каталог становится недоступен для **всех** посетителей сайта. ## Что нужно сделать Залогиньтесь как `demo` / `demo`, отправьте на `/profile/settings` JSON-payload, который через `__proto__` загрязнит глобальный прототип, и убедитесь, что `/catalog` начал отдавать 500. После этого запросите `/api/incident-response` — он зафиксирует инцидент и вернёт flag. ## Учётные данные - Обычный пользователь: `demo` / `demo` - Администратор: `admin` / `SuperSecret` Для эксплуатации хватит обычного пользователя — endpoint `/profile/settings` доступен всем аутентифицированным.
🚧 Сайт в разработке. Полный функционал пока недоступен. Все вопросы — support@hackandfix.ru