Обмен паролями и ссылками между устройствами — закрыл в Copy Sync дыру, про которую честно предупреждал в прошлом посте

от автора

Короткое напоминание

Месяц назад я тут рассказывал, как сделал свой сервис для обмена чувствительной и приватной информацией Copy Sync — устроенный так, чтобы мой сервер физически не мог прочитать ваши пароли и ссылки. Текст шифруется прямо на вашем устройстве, на сервер уезжает уже зашифрованная каша, ключа от неё у меня нет.

Многие тогда справедливо спросили в комментах: «а ключи-то от шифрования откуда устройства берут?» Вопрос в точку. И в той статье я сам честно написал, что тут осталась слабое место. Вот её и чиню.

В чём была дыра

Объясню простым языком:

Чтобы зашифровать сообщение для вашего второго устройства, первому нужен «публичный ключ» второго, что-то вроде открытого почтового ящика, куда можно бросить письмо, но достать его может только владелец. Вопрос: откуда первое устройство этот ящик берёт? Спрашивает у сервера. У моего сервера.

И вот тут собака зарыта. А что если сервер (или тот, кто его взломал) вместо настоящего ящика вашего устройства подсунет свой? Тогда:

  • ваше первое устройство шифрует письмо в подставной ящик;

  • сервер его спокойно открывает, читает, потом перепаковывает в настоящий ящик и отправляет дальше;

  • второе устройство получает письмо как ни в чём не бывало.

Оба ваших устройства довольны, а посередине кто-то всё прочитал. Это называется «человек посередине» (man-in-the-middle). И самое обидное шифрование тут ни при чём, оно идеальное. Просто зашифровали не туда. А «не туда» подсунул именно тот, кому мы вроде как не должны были доверять, мой сервер.

Неприятно, что мой же сервис, про который я писал «нечем вас прочитать», в этом сценарии всё-таки мог. Так не пойдёт.

Как защититься

Способ старый и проверенный, такой же используют в Signal и WhatsApp, когда показывают «код безопасности». Идея простая:

У каждого ящика-ключа есть короткий отпечаток — набор букв и цифр, который из этого ключа однозначно вычисляется. Как отпечаток пальца: у разных ключей он разный, у одного и того же — всегда одинаковый.

Вы открываете Copy Sync на двух своих устройствах и сравниваете отпечатки глазами. Совпали — значит, между устройствами реально один и тот же ключ, никто посередине не встрял. А если сервер подсунул свой ключ — отпечаток сразу разойдётся, и вы это увидите. Подделать его нельзя: отпечаток намертво привязан к ключу.

Пять секунд работы — и MITM из «незаметно читает всё» превращается в «попадётся на первой же сверке».

А теперь — самое главное, ради чего и пишу

Когда вы сверили отпечатки и нажали «Сверено», эту галочку надо где-то запомнить. И вот тут у меня был соблазн сделать «как удобно»: сохранить её на сервере, чтобы синхронизировалась между устройствами.

Я этого не сделал. Сознательно.

Смотрите. Мы защищаемся от кого? От сервера. А теперь представьте, что я бы доверил тому же серверу хранить отметку «этому ключу можно верить». Взломщик просто поставил бы галочку «проверено» своему поддельному ключу и вся защита превратилась бы в спектакль. Нельзя ставить сторожить дверь того, от кого ты эту дверь запираешь.

Поэтому галочка «сверено» живёт только в вашем браузере и на сервер не уходит вообще никогда. У этого есть приятный побочный эффект: галочка привязана к самому ключу. Если сервер завтра попробует подменить ключ, отметка «проверено» слетит сама собой, и устройство снова покажет «не сверено». Вы заметите, что что-то поменялось. Подмена ключа автоматически сбрасывает доверие — это не баг, это и есть защита.

Цена честная: сверять придётся на каждом устройстве отдельно. Но это в сто раз лучше, чем доверять «проверку» тому, кого проверяешь.

Бонусом — подключение второго устройства по QR

Заодно сделал удобную мелочь. Раньше, чтобы добавить второе устройство, надо было вводить пароль. Теперь на первом устройстве показывается QR-код, вы сканируете его вторым и всё, вы в системе. Без пароля.

И тут важная деталь в том же духе: по QR передаётся только разовый «пропуск» (живёт 5 минут, срабатывает один раз). Ключи шифрования по нему не передаются — второе устройство создаёт свои собственные, прямо у себя, и они его никогда не покидают. Так что даже перехваченный QR не даст доступа к вашим данным.

Честно о том, чего ещё нет

Как и в прошлый раз — про минусы сам, без прикрас:

  1. Сверка ручная. Она работает, только если вы реально сравнили отпечатки. Не сравнили — защита не сработает. Я не заставляю это делать насильно, но честно: это инструмент, а не автоматический щит.

  2. Сервис пока не предупреждает сам, если ключ вдруг сменился — он лишь снимает галочку «проверено». Автоматическое уведомление «эй, ключ поменялся!» следующая задача.

  3. Это по-прежнему пет-проект одного человека. Веб-версия работает, расширение и мобильные приложения — в планах. Код по-прежнему весь открыт — можете сами проверить, а не верить на слово.

Посмотреть

  • Сайт: copysync.ru (заведите два устройства, подключите второе по QR и сверьте отпечатки — увидите всё своими глазами)

  • Исходники: gitlab.com/razgiva/copy-sync

    Буду рад вопросам и критике — особенно от тех, кто шарит в безопасности. Нашли, как обойти сверку, — для меня это ценнее лайка.

А вопрос к вам такой: вы вообще когда-нибудь сверяли «код безопасности» в Signal или WhatsApp? Или это та штука, которую все видели, но никто ни разу не нажимал?

ссылка на оригинал статьи https://habr.com/ru/articles/1049780/