diff --git a/docs/ip-audit-2026-09-18.md b/docs/ip-audit-2026-09-18.md new file mode 100644 index 0000000..c731e19 --- /dev/null +++ b/docs/ip-audit-2026-09-18.md @@ -0,0 +1,118 @@ +# Что клиент получает вместе с продуктом и что из этого читается (аудит 18.09.2026) + +Вопрос: клиент получает bj и может отдать его на разбор — человеку или нейросети. +Насколько легко по дистрибутиву восстановить, как продукт устроен, и повторить его? +Ниже — не рассуждения о концепции, а проверка реальных файлов: `/opt/bj/bj-server` +(сборка 18.09), `crypto-service.jar`, архивы кабинета, скрипты, образ установки. + +## Как собирается + +Сборка правильная: `go build -trimpath -ldflags "-s -w"` для всех бинарей — таблица +символов и отладочная информация убраны, локальные пути машины сборки не попадают. +Но у Go это не даёт того, что даёт у C: **имена функций остаются** в таблице +`pclntab`, без них не работают паники и сборщик мусора. В боевом `bj-server`: + +| Что читается прямым `strings` | Сколько | +|---|---| +| имена функций пакета `lkgateway` | 4 672 | +| пути исходников вида `Bridge-and-Join-s/internal/…/файл.go` | 4 931 | +| SQL-запросы (`SELECT …`) | 214 | +| таблицы учётных систем `OD_*`, `D_B_*`, `FTV_M2M*` | 32 уникальных | +| упоминания типов сообщений НРД (M2M01…, ORDXM, MF010, MS010, TransferDecision…) | 173 | +| фрагменты HTML-шаблонов | 739 | +| русский текст (подсказки, справка, тексты интерфейса) | ≈190 000 символов | + +Имена функций и путей — это готовая карта проекта: `lkgateway.lkArchivePortfolio`, +`lkgateway.spectreProceeds`, `lkgateway.ApplyDecision`, `internal/lkgateway/lkflow.go`. +С такой картой декомпилятор (Ghidra с Go-плагином) восстанавливает структуру за часы, +а нейросети достаточно скормить вывод `strings`. + +## Что именно утекает и насколько это ценно + +**1. Справка внутри бинаря — самая большая дыра.** В `bj-server` вшиты десять страниц +`/admin/help/*` общим объёмом ≈150 КБ: «Архитектура: как устроен обмен с НРД» (со +схемой контуров и адресами `edog.nsd.ru`/`WslService`), «Для разработчика Fancy» +(41 КБ — полное описание протокола событий FTV_M2M, таблиц, идентификаторов и порядка +этапов, «согласовано 10.09.2026»), QUIK, база, криптосервис, робот, ручной ввод. +Это не код — это проектная документация в чистом виде. Её не нужно даже +декомпилировать: `strings bj-server | grep -A50 'Для разработчика Fancy'`. + +**2. SQL к DEPO и SPECTRE.** Все 214 запросов лежат текстом: какие таблицы, какие +связи (`OD_RESTS.REG_3 = D_B_CONTRACTS.DOC`, `PART=39`, счета 58.01/58.05, ВЫРУЧКА), +какие поля значат что. Это месяцы разбора чужой учётной системы, сложенные в один +`grep`. Именно эта часть — знание, которого нет ни в документации Fancy, ни в открытых +источниках. + +**3. Форматы НРД.** XML собирается кодом из структур (`encoding/xml`), поэтому готовых +шаблонов в бинаре нет, но имена полей и типов сообщений видны все. Сами форматы — +публичная документация НРД, здесь утекает не формат, а *знание, какие поля и как +заполнять* (префиксы `req:/typ:`, `K`, порядок 16/1 → MS010). + +**4. `crypto-service.jar`** — Java. Байт-код декомпилируется в почти исходник любым +JD-GUI/CFR. Наших классов немного (`ru.zetit.bridgeandjoins.crypto.*`, ~15 классов — +обёртка над Валидатой и gRPC), остальное — библиотеки. Утечка умеренная: это клей. + +**5. Скрипты и ретранслятор.** Bash-помощники (`bj-keymedia-*`, 510 строк), PHP-ретранслятор +кабинета (629 строк), `install.sh`, `bj-firstboot` — исходники по природе. Ценности не +несут: тонкие обёртки. Это нормально. + +**6. Схема нашей базы** (`migrations/m2m-core/*.sql`, 12 КБ) — вшита. Мелочь. + +**Что клиенту НЕ уходит и правильно:** сервер лицензий (код, ключи подписи релизов и +лицензий), портал, артефактория. Кабинет клиента в варианте В — образец правильного +устройства: на хостинг уходит ретранслятор без логики, всё содержимое собирает ядро. + +## Лицензия как защита + +Ключ подписан Ed25519, проверяется внутри бинаря; признаки модулей спрашиваются в +9 местах (`moduleAllowed`). Ядро без лицензии продолжает работать (решение 16.09: +переводы не должны встать из-за оплаты). Это значит: лицензия сегодня управляет +*удобством* (модули, обновления), а не *возможностью* работать. Обойти проверку в +Go-бинаре — поменять один условный переход; сервер об этом не узнает, потому что +единственное, что требует токен на сервере, — скачивание обновлений. + +## Модульность — про что она + +Разделение на bj-server / bj-npr / bj-quikexport / bj-lk сделано для лицензирования и +раздельного обновления. **Защитой знаний оно не является:** каждый бинарь несёт своё +ноу-хау в том же читаемом виде, а ядро — ещё и разделы интерфейса всех модулей. +Ожидать от модульности защиты не нужно; защищать надо содержимое бинарей. + +## Честная оценка риска + +Полностью закрыться нельзя: продукт работает у клиента, на его машине, с его базами — +всё, что исполняется там, в принципе читаемо. Конкурент с доступом к Fancy и документам +НРД повторит продукт и без нашего бинаря, вопрос только времени. Поэтому цель защиты — +**не сделать невозможным, а сделать дорогим и доказуемым**: чтобы `strings` не выдавал +проектную документацию, чтобы декомпиляция стоила недель, а не часов, и чтобы факт +разбора был нарушением договора с понятными последствиями. + +## Что делать — по отдаче на вложенное + +1. **Вынести справку из клиентской сборки** (день). Страницы `/admin/help/*` собирать + только в сборку для нас (build tag `dev`) либо отдавать с портала по лицензии. + Убирает самую крупную и самую дешёвую утечку. Риска для клиентов нет: справка нужна + внедренцу, а не оператору. +2. **Обфускация Go-сборок garble** (день с прогоном тестов). `garble -literals -tiny build`: + имена функций и пакетов заменяются на случайные, строковые литералы (SQL, тексты) + шифруются и расшифровываются только при выполнении — `strings` перестаёт что-либо + давать, декомпилятор получает безымянную кашу. Seed храним у себя (`~/keys`), паники + с клиента разворачиваем `garble reverse`. Цена: сборка медленнее, трассы с клиента + нечитаемы без seed. +3. **Договор.** Лицензионное соглашение: запрет декомпиляции, реверса, передачи третьим + лицам и загрузки в сторонние сервисы (включая ИИ), ноу-хау как коммерческая тайна, + неустойка. Принятие — галочкой на портале перед скачиванием, с записью кто/когда/что + скачал. Это единственное, что работает *после* утечки. +4. **Метка сборки.** Портал уже знает лицензию скачивающего: при выдаче дистрибутива + кабинета и пакетов обновления вшивать идентификатор лицензии в архив/бинарь + (`-X` при сборке или запись в служебный раздел). Утёкший файл указывает на источник. + Для общих релизов из артефактории — подпись манифеста уже привязана к токену, добавить + журнал выдачи достаточно. +5. **Java-сервис**: ProGuard/R8 для своих классов (полдня) — либо в перспективе перенести + подпись в Go, служба маленькая. +6. **Не делать:** переносить логику работы с DEPO/НРД «в облако» — продукт обязан + работать в закрытом контуре без нас; это его свойство, а не недостаток. Не искать + защиты в модульности и в лицензии: они про деньги и удобство, не про секреты. + +Пункты 1–2 закрывают то, что находится за минуты. Пункт 3 — то, что нельзя закрыть +технически. Остальное — по мере сил.