Ключи были в безопасности. Деньги всё равно ушли
Судя по тому, что известно о взломе Binance, атакующему не понадобилось красть приватные ключи. Он зашёл через ноутбук DevOps-инженера и просто отправил системе команду на вывод. Система её выполнила — ровно так, как была спроектирована.
Мне много раз советовали, как защитить ключи. Обычно разговор шёл так:
— Надо шифровать ключи на сервере.
— Допустим. А где лежит ключ для расшифровки?
— Спрячем его.
— Обфускация не спасает. Это вопрос времени, а сейчас нейросеть разбирает чужой код за минуты.
— Тогда AWS KMS.
— KMS выдаст ключ по запросу от скомпрометированного сервера.
— Тогда отдельный изолированный сервер, который хранит ключи и подписывает.
— Ключ теперь не украсть. Но этот сервер получает из очереди сообщение «отправь столько-то туда-то» — и отправляет. Ключ в безопасности, деньги — нет.
— Поставим проверяющий сервис: перед подписью он сверяет, легитимен ли вывод.
— А где он сверяет? Во внутренней базе — её тоже можно подменить. Если же он сверяется с независимым неизменяемым источником и сам решает, подписывать ли, — мы только что изобрели смарт-контракт. Если у контракта есть вся информация и в нём нет исходной уязвимости, его не уговоришь и не взломаешь через соседний сервер.
Всё, что опирается на сервер, однажды сломают: найдётся дыра в SSH, nginx, PHP — в чём угодно. Мои сервисы снаружи ни разу не ломали. Но однажды разработчик, у которого и так был доступ к серверу, просто взял ключи и вывел деньги. Проблема почти всегда в людях.
Можно построить сверхзащищённую систему. Но деплоят в неё люди. Кто-то оставит закладку, которая по нужной команде выведет средства, да ещё и почистит логи.
Поэтому вариантов два. Либо доверять математике, как в смарт-контрактах. Либо строить то же самое на людях, как в нашем протоколе генерации ключей: несколько независимых подписантов, кворум, каждый проверяет. Но у людей замыливается глаз, и на пятый год ты жмёшь «подтвердить», не глядя.
Здесь, мне кажется, впервые по-настоящему помогают модели. Не вместо людей, а перед ними:
- на вход только строго сформированный JSON с данными транзакции, никакого «поговорить»;
- на выходе только «да» или «нет»;
- при этом у модели широкий доступ на чтение: блокчейн, базы, старые бэкапы — чтобы искать расхождения и следы подмены;
- таких моделей не одна, а, скажем, 13 разных, и нужно единогласие. Если хоть одна сомневается, всё останавливается и подключаются люди.
Модель не устаёт и не засыпает на пятом году работы. А если ложных тревог мало, люди будут относиться к каждой всерьёз.
Ключи защищать мы научились. Теперь надо защищать решение «подписывать или нет».