Обновить

Розыгрыш стула, похищение прав: что нашел пентестер в пет-проекте

Уровень сложностиПростой
Время на прочтение13 мин
Охват и читатели13K
Всего голосов 51: ↑51 и ↓0+68
Комментарии15

Комментарии 15

  • Извлекать userId только из токена/сессии и игнорировать userId, присланный клиентом.

А почему игнорировать? Я бы сравнивал... и алерт, если несоответствие.

Если сервер не принимает userId из тела запроса, то и сравнивать не нужно - он сам извлекает userId из токена и работает только с записями этого пользователя. Если же userId передаётся клиентом - проверка обязательна, чтобы не дать ему действовать от чужого имени. В данном случае предпочтительнее вообще не передавать userId в теле запроса, потому что так проще. Если userId не передается клиентом - он не может его подделать. Нет параметра - нет риска.

Не-не... давайте не отрываться от обсуждаемой фразы. А фраза однозначно утверждает, что userIdи извлекается из токена, и присылается клиентом. Согласитесь, что если имеется две независимо полученные копии одного и того же значения, вполне разумно сверить их. И если эта сверка даст отрицательный результат, то где-то имеет место быть проблема, на которую просто нельзя не реагировать.

Вопрос о том, какой должна быть эта реакция - это уже другой вопрос, за рамками. Но само рассуждение, наоборот, приводит к мысли, что наличие параметра может работать как ловушка на беспечного плохиша. Зачем упускать такую возможность?

Да, при наличии двух источников одного и того же значения (токен и тело запроса) - логично их сверить, так что вы правы) Но цель моей рекомендации - полностью исключить использование клиентского userId, потому что если клиент не может передать userId, то подделка невозможна и проверять нечего.

В случае же, если мы по какой-то причине всё же принимаем userId от клиента - да, его надо сравнивать с тем, что в токене, и при несовпадении - выдавать 403/400 или хотя бы писать alert (как вы и предложили).

Согласитесь, что если имеется две независимо полученные копии одного и того же значения, вполне разумно сверить их.

«Человек, у которого одни часы, всегда знает, который час. Человек, у которого двое часов, никогда в этом не уверен» ©

Сравнение это лишняя сущность и усложнение логики. Единственный источник правды о том кто выполняет действие, это токен. Клиент не должен иметь права голоса в этом вопросе. Если сервер в принципе не смотрит на userId из тела запроса, то уязвимости просто нет по определению. Это проще и надежнее

В более сложных системах, да и в этой тоже - для админа, например, может быть вполне легальная ситуация, когда userid в токене не совпадает с userid в теле запроса. Это просто будет означать, что залогиненный пользователь имеет право действовать от имени другого или получать информацию о другом пользователе. И сервер, естественно, это право должен проверить на этапе исполнения запроса - при авторизации.

Просто как напоминание:

  • Аутентикация: проверка кто ты есть

  • Авторизация: проверка что ты имеешь право делать

Простые правки — требование аутентификации для критичных операций, получение userId только из токена/сессии, нормализация email и скрытие приватных полей в API — закрывают основные входы для атак.

Забавно, что таблицы в pocketbase по дефолту доступны снаружи только для суперпользователей. То есть, кто-то из ваших кодеров не поленился снять это ограничение, но не стал добавлять правило @request.auth.id=user_id, которое в том же диалоге делается.

Спасибо за замечание, и вы абсолютно правы - базовые меры безопасности это must-have. Но это был первый полноценный проект моего коллеги-фронтендера, и писал он его с нуля и самостоятельно - и, как часто бывает в таких случаях, фокус был на "сделать так, чтобы работало", а не на "сделать безопасно". Главное, что он не просто оставил как есть, а пришёл к нам, попросил проверить на безопасность, признал недочёты и сам исправил все критичные уязвимости. Это и есть рост.

Отличный пример здоровой культуры в компании) Разработчик не боится показать свой проект ИБ-отделу, а ИБ-отдел не просто выдает сухой отчет, а помогает разобраться и превращает это в обучающий материал для всех. Вот такая совместная работа а не игра в кошки-мышки и растит нормальных профессионалов

Сервис дырявый весь насквозь, как будто специально для статьи сделан)

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

По самым канонам

там была бы SQL-инъекция

Очень на мой взгляд странная практика - передавать UserID с запросом - всё, что я писал даже для внутреннего использования, за последние лет 20, даже отчёты по потреблённому трафику, использовало данные либо из $_SESSION, либо через mysqli_query/pg_fetch* по полю из $_SESSION, и это делал "программист", окончивший официальное обучение аж в 1994-м году (ладно, то, что я писал 30+ лет назад вообще не подразумевало какой-либо авторизации/аутентификации - не те времена были). Но вообще, дичь, конечно, встречать в GET-запросах (которые в адресную строку подставляются) чувствительную информацию - благо, последние годы это всё "спрятали" на POST-запросами, но сама логика продолжает вызывать недоумение.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Информация

Сайт
slc.tl
Дата регистрации
Дата основания
Численность
1 001–5 000 человек
Местоположение
Россия
Представитель
Александр Шилов