Планируя переезд в Грузию, я озаботился вопросом наличия двух загранпаспортов (нового и старого образца) еще за полгода до отъезда. Сделав один, я уже подался на второй, оплатил пошлину, мне его сделали, но я не успел его забрать и уехал на недельку отдыхать в Китай... где в самолете забыл свой единственный загранпаспорт. Но это история для отдельного поста. Вернувшись, мне пришлось отказаться от уже готового паспорта, и я так и не успел сделать загран нового образца, так что решил доделать всё уже в Тбилиси.
Это история о том, как я подался на получение загранпаспорта нового образца в консульство в Тбилиси, забыл кодовое слово для доступа к анкете на сайте 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/сек
Найти скрипт для подбора кодового слова вы можете тут
Сколько времени уйдет на брутфорс?

Где ? — это максимальное количество букв, из которого, предположительно, состоит ваш пароля, а ? — это количество вариантов на каждую букву. Например, я думал, что у меня кодовое слово состоит только из русских букв и не может быть длинее 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 строк кода).
Комментарии (11)
Zara6502
05.07.2024 09:31+9в самолете забыл свой единственный загранпаспорт
забыл кодовое слово
Hidden text
какая у вас интересная и насыщенная жизнь
Zara6502
05.07.2024 09:31пупа XD а в чем проблема использовать по жизни всегда набор из 3-5 кодовых слов по настроению? или уверены что товарищ майор не сбрутфорсит вашу пупу?
Snooper
05.07.2024 09:31+8Осталось неясным зачем понадобилось брутфорсить. Этот сайт нужен только для генерации pdf с анкетой для распечатывания. Никаких записей в очередь или ещё чего-то такого там нет.
Можно просто создать новую анкету. Ещё удобно, что там можно скачать json с данными анкеты, чтобы в следующий раз загрузить из него и отредактировать, чтобы не вбивать всё по новой.
Wolframium13
Короче, быстрее в Россию слетать за паспортом.