stihl не предоставил(а) никакой дополнительной информации.
В этой статье я расскажу, как при проведении пентеста вскрыл целый ряд уязвимостей одного веб‑сервиса, которые в итоге дали мне доступ к аккаунтам любых пользователей. Я вкратце опишу каждую уязвимость, а затем посмотрим, что надо сделать, чтобы закрыть подобные дыры.
Если указываем существующую учетку, получаем сообщение «Введен неверный пароль» либо «Превышено количество попыток входа с неверным паролем». Если же пользователя с таким логином нет, то в ответе сервера будет сообщение «Ваши данные не найдены в системе. Проверьте правильность указанных данных».
Сообщение для валидного логина
Сообщение для невалидного логина
Я запустил автоматизированный подбор по словарю и нашел некоторое количество валидных логинов.
Страница ввода кода из SMS
Изучив код этой страницы, я нашел интересный параметр — mode4. Здесь он имеет значение sms.
Параметры GET-запроса страницы ввода кода из SMS
Я перебрал возможные значения этого параметра и нашел несколько таких, при которых нас не перенаправляет обратно на страницу ввода логина и пароля.
Для просмотра ссылки Войдиили Зарегистрируйся
Интересные значения, которые может принять параметр mode4
Здесь интереснее всего значение mode4=registration, которое перенаправляет на страницу завершения регистрации в личном кабинете. Там пользователь задает себе логин и пароль, но при этом уже задал и подтвердил номер телефона.
Вид страницы при mode4=registration
Вводим и подтверждаем пароль одного из полученных ранее пользователей, и нам удается зайти в личный кабинет, минуя двухфакторную авторизацию. Также, если изменить логин на этой же странице, он сохраняется измененным.
Мое внимание привлекли cookie на странице смены пароля. Выяснилось, что содержимое страницы не зависит ни от каких значений, кроме UserStatus. А это значение перманентно и уникально для каждого пользователя.
Cookie UserStatus
Что будет, если подменить UserStatus одного пользователя аналогичным значением другого? Логин и пароль оставим прежними. После отправки запроса приходит ответ, что все прошло успешно. Спокойно извлекаем из него новые cookie, логин, пароль и UserToken, но уже для сессии другого юзера — того, чей UserStatus использовался. Также приходит редирект обратно на страницу входа. Если бы смена не была успешной, этим параметрам из cookie присваивались бы значения deleted и тоже происходил бы редирект.
Теперь можем войти снова — используя новые логин и пароль. Нас опять попытается остановить 2FA, то есть запрос кода из SMS. Но мы уже знаем, что делать в этом случае, и без труда проникаем в личный кабинет пользователя, UserStatus которого мы использовали.
Изменение логина и пароля пользователя
Мы не знаем UserStatus для других пользователей, но можем попробовать подобрать это значение. Его длина — 40 бит. Это 240 вариантов, то есть около 1,1 триллиона значений. Многовато для перебора!
Но если разобрать любое известное нам значение UserStatus побитово, то можно увидеть, из чего оно состоит. Половина каждого байта определяет поле, а вторая половина — значение этого поля.
Побитовый разбор значений cookie UserStatus
Теперь мы можем подбирать значения лишь 20 бит. Число вариантов сокращается до 220, то есть около 1,05 миллиона возможных значений переменной UserStatus.
Результат эксплуатации: несколько захваченных аккаунтов, потенциальная возможность захвата всех пользовательских аккаунтов за чуть более чем миллион запросов.
Вот что я порекомендовал сделать заказчику, чтобы устранить уязвимости:
Pentest Award
Этот текст получил первое место на премии Pentest Award 2024 в категории «Пробив web». Это соревнование ежегодно проводится компанией Awillix.warning
Статья имеет ознакомительный характер и предназначена для специалистов по безопасности, проводящих тестирование в рамках контракта. Автор и редакция не несут ответственности за любой вред, причиненный с применением изложенной информации. Распространение вредоносных программ, нарушение работы систем и нарушение тайны переписки преследуются по закону.
Перечисление пользователей
- Уровень опасности: средний
Если указываем существующую учетку, получаем сообщение «Введен неверный пароль» либо «Превышено количество попыток входа с неверным паролем». Если же пользователя с таким логином нет, то в ответе сервера будет сообщение «Ваши данные не найдены в системе. Проверьте правильность указанных данных».
Я запустил автоматизированный подбор по словарю и нашел некоторое количество валидных логинов.
Спреинг паролей
- Уровень опасности: средний
Обход 2FA
- Уровень опасности: критический
Изучив код этой страницы, я нашел интересный параметр — mode4. Здесь он имеет значение sms.
Я перебрал возможные значения этого параметра и нашел несколько таких, при которых нас не перенаправляет обратно на страницу ввода логина и пароля.
Для просмотра ссылки Войди
Здесь интереснее всего значение mode4=registration, которое перенаправляет на страницу завершения регистрации в личном кабинете. Там пользователь задает себе логин и пароль, но при этом уже задал и подтвердил номер телефона.
Вводим и подтверждаем пароль одного из полученных ранее пользователей, и нам удается зайти в личный кабинет, минуя двухфакторную авторизацию. Также, если изменить логин на этой же странице, он сохраняется измененным.
Похищение учетки
- Уровень опасности: критический
Мое внимание привлекли cookie на странице смены пароля. Выяснилось, что содержимое страницы не зависит ни от каких значений, кроме UserStatus. А это значение перманентно и уникально для каждого пользователя.
Что будет, если подменить UserStatus одного пользователя аналогичным значением другого? Логин и пароль оставим прежними. После отправки запроса приходит ответ, что все прошло успешно. Спокойно извлекаем из него новые cookie, логин, пароль и UserToken, но уже для сессии другого юзера — того, чей UserStatus использовался. Также приходит редирект обратно на страницу входа. Если бы смена не была успешной, этим параметрам из cookie присваивались бы значения deleted и тоже происходил бы редирект.
Теперь можем войти снова — используя новые логин и пароль. Нас опять попытается остановить 2FA, то есть запрос кода из SMS. Но мы уже знаем, что делать в этом случае, и без труда проникаем в личный кабинет пользователя, UserStatus которого мы использовали.
Мы не знаем UserStatus для других пользователей, но можем попробовать подобрать это значение. Его длина — 40 бит. Это 240 вариантов, то есть около 1,1 триллиона значений. Многовато для перебора!
Но если разобрать любое известное нам значение UserStatus побитово, то можно увидеть, из чего оно состоит. Половина каждого байта определяет поле, а вторая половина — значение этого поля.
Теперь мы можем подбирать значения лишь 20 бит. Число вариантов сокращается до 220, то есть около 1,05 миллиона возможных значений переменной UserStatus.
Результат эксплуатации: несколько захваченных аккаунтов, потенциальная возможность захвата всех пользовательских аккаунтов за чуть более чем миллион запросов.
Выводы
Итак, мы поняли, что есть возможность менять логины и пароли всех пользователей, UserStatus которых содержит те же поля, что известные нам. Затем мы можем пройти аутентификацию от имени этих пользователей в обход 2FA. Во время тестирования мне удалось захватить несколько аккаунтов и установить, что можно получить доступ к любой учетной записи чуть более чем за миллион запросов.Вот что я порекомендовал сделать заказчику, чтобы устранить уязвимости:
- Перечисление пользователей: унифицировать ответ сервера при вводе валидных и невалидных учетных данных.
- Спреинг паролей: каждый раз увеличивать время блокировки учетных записей после ввода неверных логина и пароля.
- Байпас 2FA: после того как пользователь прошел регистрацию, не редиректить его в личный кабинет, а перенаправлять на страницу ввода логина и пароля.
- Похищение учетных записей: использовать связку из нескольких параметров, которые уникально идентифицируют пользователя.