3.8 KiB
NarodUslugi - полный разбор (пошагово)
Этот разбор объясняет, как устроен сервис и как решатель получает флаг. Ссылки идут на локальные файлы задачи в этой директории.
1) Входные данные и их источники
- URL цели, partA и user можно читать из
target.txtили передать через CLI. - Поведение сервера описано в
files/server.js. - Логика решателя находится в
solver.py. - Значения окружения указаны в
web_naroduslugi_6.yml.
2) Формула пароля (на сервере)
В files/server.js сервер считает пароль так:
PASS = sha1(f"{PWD_PART_A}:{PWD_PART_B}").hexdigest()[:12]
partA у нас есть, но partB скрыт.
3) Где спрятан partB
Эндпоинт /assets/app.js.map отдает sourcemap со строкой:
pepper_xor_hex(hex-строка)
Она вычисляется так:
pepper_xor_hex = xorHex(PWD_PART_B, sha1(user)[:6])
Значит partB можно восстановить, если известен user.
4) Как восстановить partB
Шаги, которые делает solver.py:
mask = sha1(user).digest()[:6]- Преобразовать
pepper_xor_hexв байты. - XOR-нуть каждый байт с
mask(по кругу). - Декодировать результат как UTF-8 и получить
partB.
После этого вычисляется пароль:
password = sha1(f"{partA}:{partB}").hexdigest()[:12]
5) Trusted-device логин для доступа к экспорту профиля
Есть альтернативная авторизация, описанная в /.well-known/:
- Заголовки:
X-TSиX-Trusted-Device X-Trusted-Device = hex(hmac_sha1(pass, ts))tsдолжен быть в окне 120 секунд
Если заголовки валидны, сессия помечается как mfa=true, но
mfaOtp=false. Это дает доступ к /profile и /profile/export.
6) Экспорт OTP-секрета отдается с маской
/profile/export?fmt=ini возвращает:
otp_secretс заменой последних 2 base32-символов на??
Есть CSRF-проверка: нужен Referer: /profile.
Решатель выставляет этот заголовок.
7) Брут последних 2 base32-символов
Алфавит base32 длиной 32, значит всего 32 * 32 = 1024 вариантов. Решатель перебирает все кандидаты:
- Логинится обычным способом (без trusted заголовков).
- Считает TOTP для кандидата.
- POST на
/mfaсotp. - При успехе открывает
/walletи/wallet/drain.
8) Синхронизация времени
Решатель читает /__status__, чтобы получить смещение времени сервера
и учитывать его при генерации TOTP (защита от дрейфа часов).
9) Получение флага
Если OTP верный, сессия получает mfaOtp=true, и /wallet/drain
возвращает флаг.
10) Важные ловушки
- Повторный trusted-логин во время активного окна доверия вызывает бан.
- Если trusted-сессия протухла без OTP, при следующем запросе будет бан.
- Решатель использует отдельные cookie-jar и лимит попыток на сессию.