Посмотрим на
исходный код сервиса.
Список всех доступных для пользователя id можно получить по адресу
/data
.
Если есть id, то данные можно получить с помощью запроса на адрес
/data/id
.
Для доступа к данным сервис требует токен для аутентификации. У нас есть доступный
токен, но у него истёк срок годности, и сервис его больше не принимает.
Посмотрим в коде,
как эти токены генерируются. Токен получается шифрованием JSON вида
{ “userId” : “id”, expireDate: “date”}
и последующим кодированием его в base64. Сервис использует RSA для шифрования, и публичный ключ можно получить запросом по адресу
/key
.
Сделаем запрос: e = 30593, n = 66043. Т.к. n достаточно маленькое, то мы легко можем посчитать приватный ключ.
Для этого разложим n на простые множители: 211 * 313.
Вычислим
функцию Эйлера от n: ?(n) = (211 — 1)(313 — 1) = 65520.
Получим d = e-1(mod ?(n)) = 257.
Обратный элемент по модулю можно посчитать с помощью
расширенного алгоритма Эвклида.
Вычислив приватный ключ, расшифруем доступный нам токен.
Получим следущий JSON:
{"userId":"448f0a79-e2d8-4ccd-9009-53858914dcaa","expireDate":"2018-12-06T14:38:00.898026+00:00"}
Заметим, что
сервису достаточно, чтобы пользователь с данным userId существовал и expireDate был меньше, чем текущее время на сервере.
То есть, зная userId, мы можем сгенерировать новый валидный токен.
Для этого возьмем expireDate достаточно большим, чтобы пройти проверку — например
{"userId":"448f0a79-e2d8-4ccd-9009-53858914dcaa","expireDate":"2100-01-01T12:00:00.000000+00:00"}
.
Шифруем наш новый токен с помощью публичного ключа.
Сделав запрос к
/data
, узнаем, что пользователь создал сообщения с идентификаторами от 1 до 4.
Переберем их все.
Среди них чудо-фраза:
Новый год стучится в дверь, открывай ему скорей!.