Как я потерял и брутфорсил кодовое слово на сайте загранпаспортов МИДа РФ и автоматизировал получение загранпаспорта

от автора

Планируя переезд в Грузию, я озаботился вопросом наличия двух загранпаспортов (нового и старого образца) еще за полгода до отъезда. Сделав один, я уже подался на второй, оплатил пошлину, мне его сделали, но я не успел его забрать и уехал на недельку отдыхать в Китай… где в самолете забыл свой единственный загранпаспорт. Но это история для отдельного поста. Вернувшись, мне пришлось отказаться от уже готового паспорта, и я так и не успел сделать загран нового образца, так что решил доделать всё уже в Тбилиси.

Это история о том, как я подался на получение загранпаспорта нового образца в консульство в Тбилиси, забыл кодовое слово для доступа к анкете на сайте zp.midpass.ru, перерыл весь код их фронтенда и вспомнил комбинаторику, чтобы восстановить это слово. А также готовый код для тех, кто попал в такую же беду и бот, который нажимает одну кнопку раз в день.

Что за кодовое слово?

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

Когда я через 2 недели после создания заявки зашел потыкать кнопочки, я понял, что забыл кодовое слово и ни один из вариантов не подходил. По скорости появления ошибки и отсутствию сетевых запросов, стало понятно, что все шифрование происходит прямо внутри браузера. Тогда я еще надеялся, что программисты из госструктур просто хранят мое кодовое слово где-нибудь в local storage в открытом виде, но как же я ошибался…

Как на самом деле все устроено

Первое, что я попытался сделать, это посмотреть сохраненные данные сайта

Системы аккаунтов на сайте нет: заходишь, создаешь заявку, она сохраняется в браузере. Вся информация, не скрытая под кодовым словом (ФИО, дата создания, id) в чистом json, а вот в зашифрованном Request#[uuid вашей заявки] хранятся сами данные заявления. Очевидно, данные в формате base64, так что пробуем декодировать:

На этом моменте я застрял на пару недель, потому что не знал, что делать дальше. Нужно было откопать кусок кода, который отвечал за шифрование и кодирование в base64 с помощью кодового слова. Не найдя в чатике людей, которые уже делали что-то подобное, я решил покопаться прямо в коде сайта и вскоре нашел, что искал:

this.cryptoProvider.decryptData(itemJson.data, passPhrase) === 'DecryptTestMessage'

Эта строка кода расшифровывает то самое значение в base64 из localstorage, и если оно равно «DecryptTestMessage», значит кодовое слово правильное. Осталось найти cryptoProvider среди скомпилированного js.

Что здесь происходит? Задумка автора это или оптимизация компилятора – останется загадкой 🤔

Что здесь происходит? Задумка автора это или оптимизация компилятора – останется загадкой 🤔

Вот вам и вся криптография сайта МИДА рф: под капотом оказался DES — стандарт, разработанный америкой и прозападный CryptoJS (https://cryptojs.gitbook.io/docs)

Начинаем брутфорс

Я попросил моего более умного друга, который помнит свое кодовое слово, дать мне его зашифрованный DecryptTestMessage (+ небольшое приключение как достать localstorage с андроида, потому что он заполнял анкету на телефоне) и написал скрипт, который можно исполнить прямо на странице с заявкой. В результате я получил скорость около 16666 комбинаций/сек, с такой скоростью я мог бы просто забить и быстрее заново пройти очередь, чем 3 месяца брутфорсить с открытым браузером. Поэтому я переписал скрипт сначала на Bun.sh (серверный рантайм для js), а потом, ради интереса, и на Node.js. К моему удивлению результат не сильно разнится.

Итоговый бенчмарк (apple m1 pro):

  • Браузер: 16 666/сек

  • Node.js: 86 206/сек

  • Bun: 98 039/сек

Найти скрипт для подбора кодового слова вы можете тут

Сколько времени уйдет на брутфорс?

Я на математику в школе не ходил, поэтому попросил посчитать за меня chatgpt

Я на математику в школе не ходил, поэтому попросил посчитать за меня chatgpt

Где 𝑛 — это максимальное количество букв, из которого, предположительно, состоит ваш пароля, а 𝓂 — это количество вариантов на каждую букву. Например, я думал, что у меня кодовое слово состоит только из русских букв и не может быть длинее 5 символов (хотя может быть и короче), тогда подставляем переменные и получаем 40358373 комбинаций. Со скоростью 100.000 комбинаций в секунду мне потребуется всего ~6.7 минут, чтобы найти пароль (А ведь можно запустить в несколько потоков!). А вот если я не знаю, использовал ли я заглавные буквы в пароле, то придется потратить около 9 суток — 66 комбинаций вместо 33

Стоит ли оно того?

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

А что делать дальше? Записываться в очередь уже на другом сайте — https://q.midpass.ru/ и ждать примерно 3-6 месяцев записи на подачу документов. В чатиках я встретил человека, который ждал 3.5 месяца, и когда подошла очередь, ему прислали дату на послезавтра. Он отказался и его место откатилось снова на последние места (в данный момент около 3500). В какой-то момент мне надоело самому тыкать кнопку «Подтвердить заявку» каждый день, так что я написал самого простого (по моему мнению) бота, который делает это за вас: https://github.com/VityaSchel/q-midpass-ru-autoconfirm (всего 170 строк кода).


ссылка на оригинал статьи https://habr.com/ru/articles/826882/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *