Files
validator/ctfcup2025-school-final/sploits/sonobank

Sonobank: описание, уязвимости + PoCs, харденинг

Что за сервис

UDPсервис, говорящий на SysExфреймах (опкоды 0x010x05). Основные операции:

  • 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. Факторизует модуль, решает дискретный логарифм, восстанавливает общий ключ и расшифровывает AESCBC.
  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.