55 lines
4.3 KiB
Markdown
55 lines
4.3 KiB
Markdown
# Sonobank: описание, уязвимости + PoCs, харденинг
|
||
|
||
## Что за сервис
|
||
UDP‑сервис, говорящий на SysEx‑фреймах (опкоды 0x01–0x05). Основные операции:
|
||
- `Diag` — проверка живости.
|
||
- `Put` — принимает Lua DSP‑скрипт, шифрует и сохраняет как патч (`patch_id`, приватный ключ выдаётся в ответе).
|
||
- `Get` — возвращает публичный ключ и шифротекст патча по `patch_id`.
|
||
- `RenderHash` — расшифровывает Lua и вызывает `sample()`, хешируя значения.
|
||
- `GetCryptoParams` — отдаёт параметры группы.
|
||
|
||
Патчи лежат на диске как `data/<uuid>.pb` в TLV‑формате: k, c1, ct, iv, End.
|
||
|
||
## Уязвимость 1: Lua не песочница, утечки через RenderHash
|
||
- `lua-sandbox::render_hash` создаёт полноценный Lua без ограничения stdlib; доступны `io.open`, `os`, и т.п.
|
||
- Ошибки из Lua пробрасываются в ответ `RenderHash` (server возвращает `Error("Couldn't compute hash: <сообщение>")`).
|
||
- Итог: любой может загружать произвольный Lua и читать локальные файлы, затем вернуть их содержимое через `error()`.
|
||
|
||
### Эксплуатация (PoC `lua_poc.py`)
|
||
Выгружает содержимое чужого патча `data/<victim_patch_id>.pb`, расшифровывает его и печатает исходный Lua (в нём хранится флаг).
|
||
```
|
||
python3 sploits/sonobank/lua_poc.py <host> <victim_patch_id> [port=5004]
|
||
```
|
||
Скрипт:
|
||
1) Делает `Put` с Lua, который читает `data/<victim>.pb` и бросает его в ошибке как hex.
|
||
2) Делает `RenderHash` на своём патче, получает `Error`, парсит TLV, выводит расшифрованный Lua жертвы.
|
||
|
||
### Харденинг
|
||
- Создавать Lua с отключёнными I/O: `Lua::new_with(mlua::StdLib::BASE | ... )` без `IO`/`OS`, или `set_sandboxed(true)`.
|
||
- Явно очищать/затирать глобальные таблицы (`io`, `os`, `package`).
|
||
- Не выдавать текст ошибки пользователю — логировать на сервере, клиенту слать общий код.
|
||
|
||
## Уязвимость 2: Крипто на слабой группе, dlog решается
|
||
- Кольцо — GF(2)[x]/P(x), которое притворяется GF(p).
|
||
- Полином P(x) раскладывается как Q(x)^5, поэтому порядок мультипликативной группы (2^210 - 1) умножить на небольшое число.
|
||
- В этом случае порядок группы равен (2^210 - 1) * 8, Этот порядок гладкий и позволяет алгоритмом Полига-Хеллмана посчитать длог. Для ускорения сначала считаем по модулю Q(x).
|
||
|
||
### Эксплуатация (PoC `crypto_sploit.py`)
|
||
Запуск под `sage -python` (используется `sage.all`):
|
||
```
|
||
sage -python sploits/sonobank/crypto_sploit.py
|
||
```
|
||
Скрипт:
|
||
1) Берёт `GetCryptoParams`, затем `Get` по `flag_id` (`patch_id`).
|
||
2) Факторизует модуль, решает дискретный логарифм, восстанавливает общий ключ и расшифровывает AES‑CBC.
|
||
3) Печатает Lua с флагом.
|
||
|
||
### Харденинг
|
||
- Заменить модуль на неприводимый с удачной степенью, например, 127 (2^127 - 1 является простым числом Мерсенна). Тогда группа будет вполне подходящей.
|
||
|
||
## Полезные файлы
|
||
- `sploits/sonobank/lua_poc.py` — утечка через Lua.
|
||
- `sploits/sonobank/crypto_sploit.py` — взлом DLog.
|
||
- `services/sonobank/crates/lua-sandbox/src/lib.rs` — источник Lua уязвимости.
|
||
- `services/sonobank/crates/crypto/src/encryption.rs` — уязвимый DH.
|