Init. import

This commit is contained in:
Caplag
2025-12-22 05:19:38 +03:00
commit 39a4c5e8ca
58 changed files with 3063 additions and 0 deletions

91
GAME/narod/writeup.md Normal file
View File

@@ -0,0 +1,91 @@
# 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 и лимит попыток на сессию.