# 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`:

1. `mask = sha1(user).digest()[:6]`
2. Преобразовать `pepper_xor_hex` в байты.
3. XOR-нуть каждый байт с `mask` (по кругу).
4. Декодировать результат как 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 вариантов.
Решатель перебирает все кандидаты:

1. Логинится обычным способом (без trusted заголовков).
2. Считает TOTP для кандидата.
3. POST на `/mfa` с `otp`.
4. При успехе открывает `/wallet` и `/wallet/drain`.

## 8) Синхронизация времени

Решатель читает `/__status__`, чтобы получить смещение времени сервера
и учитывать его при генерации TOTP (защита от дрейфа часов).

## 9) Получение флага

Если OTP верный, сессия получает `mfaOtp=true`, и `/wallet/drain`
возвращает флаг.

## 10) Важные ловушки

- Повторный trusted-логин во время активного окна доверия вызывает бан.
- Если trusted-сессия протухла без OTP, при следующем запросе будет бан.
- Решатель использует отдельные cookie-jar и лимит попыток на сессию.

