⚡ Как я стал админом одним POST-запросом: Register Admin Challenge в OWASP Juice Shop
⚡ Как я стал админом одним POST-запросом: Register Admin Challenge в OWASP Juice Shop Гоняю по вечерам OWASP Juice Shop - магазинчик, специально напичканный дырами для тренировки. Взялся за челлендж «Register Admin» - зарегистрировать юзера с правами администратора. Точка входа 🔍 Регистрация идёт через авто-сгенерённый CRUD - POST /api/Users. Рука сама тянется подкинуть лишнее поле в JSON: JSON { "email": "x@y.z", "password": "123", "role": "admin" } Сервер честно кладёт всё тело запроса в модель. Вайтлиста нет. Клиент попросил роль - клиент получил роль. Классика mass assignment: доверять инпуту от юзера - как оставлять шелл с root на проде. Бам - админка за один запрос. 💥 Бонус-раунд: выбери правильный фикс 🎯 К задачке есть задачка посложнее - найти строку с багом и выбрать, как её починить. Виноват хук resource.create.send.before(...): последнее место, где можно перетереть роль до сохранения, - пропущено. Фиксы: ❌ Добавить 'role' в exclude - обманка. В finale это работает на сериализацию ответа, а не на запись. Баг живее всех живых. ✅ Форсить роль на сервере: context.instance.role = 'customer' - критичные поля выставляет только бэк. Правильный фикс. ❌ «Если роль пришла - оставь как есть» - это не фикс, это официальное сохранение уязвимости 🍬 ❌ Удалить несвязанный код - remediation by deletion, мимо кассы. Выводы 💻 Увидел авто-CRUD (finale, loopback) - шли всё, что модель не должна принимать: role, isAdmin, balance. «Не возвращается в ответе» ≠ «нельзя записать». Исправление одно: критичные поля задаёт только сервер. Период. Админы, которые думают, что их код безопасен, - мой любимый вид дичи 🦌