user12173780

user12173780

Веб-разработка, AppSec. Разбираю свои ошибки публично, чтобы не повторять. safekom.ru
Пикабушник
Дата рождения: 1 января
в топе авторов на 517 месте
100 рейтинг 1 подписчик 0 подписок 1 пост 0 в горячем

Три месяца пилю свой менеджер паролей, потому что задолбался с info.txt в каждой папке проекта

Я веб-разработчик. Годами у меня повторялся один и тот же сценарий: в папке очередного проекта лежал файл info.txt. Доступ к базе, ключ от хостинга, API-токен, пароль от админки заказчика, всё вперемешку, зато по папкам и всегда под рукой.

Проблемы начинались, когда доступ надо было кому-то передать. Найти актуальную версию пароля, не перепутать со старой, отправить нужному человеку и не оставить секрет навсегда болтаться в переписке. Каждый раз небольшая археологическая экспедиция по собственным старым сообщениям, и заканчивалась она обычно тем, что пароль всё-таки оставался в чате.

Плюс к файлу секреты расползались по SSH-конфигам, .env, настройкам IDE, автозаполнению браузера. После смены пароля надо было вспомнить, где ещё лежит старое значение, и я почти всегда что-нибудь пропускал.

Готовых менеджеров хватает, но я занимаюсь ещё и безопасностью, поэтому вопросы к ним у меня возникали не самые удобные. Может ли сотрудник сервиса прочитать мой сейф? Что именно сервер видит во время обычной работы? Что останется у атакующего, если он утащит базу вместе с бэкапами? И насколько сильно я вообще завишу от чужого сервиса, если в нём лежат ключи от инфраструктуры.

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

Отсюда сразу вылезает неочевидная задача. Войти можно тремя способами: мастер-паролем, по passkey (биометрия или физический ключ) и одноразовым кодом восстановления. Все три должны в итоге открыть один и тот же ключ хранилища, но ни один из них не должен дать этот ключ серверу. Решается это тем, что ключ лежит на сервере в трёх разных зашифрованных обёртках, и каждый способ входа умеет развернуть свою.

За три месяца получилось следующее: личные и командные сейфы, вход по паролю или по passkey, гостевые ссылки для разовой передачи доступа, экстренный доступ для доверенного человека. Архитектуру переписывал трижды, причём не ради красоты кода, а потому что каждый раз появлялось требование, которое старая модель просто не могла выразить.

По дороге нашёл у себя восемь неприятных багов. И вот что интересно: ни один из них не был ошибкой в криптографии. Argon2id, AES-GCM, X25519 это готовые библиотеки, они работали ровно так, как написано в документации. Ломалось всё, что я писал сам вокруг них.

Самый обидный баг: при сериализации публичного ключа терялся один-единственный нулевой байт. Координата должна занимать ровно 32 байта, а функция возвращала её как число, то есть без ведущих нулей, и иногда получался 31 байт. Итог: примерно у одного процента пользователей passkey успешно регистрировался, а войти по нему было нельзя никогда. Сначала я неделю грешил на кривые браузеры и конкретные модели ключей.

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

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

Отдельно скажу то, о чём производители менеджеров паролей обычно молчат. Клиентское шифрование защищает данные от кражи базы. Оно не защищает от заражённого устройства, не защищает от XSS в самом приложении, и не защищает от ситуации, когда владелец сервиса подменит вам JavaScript в браузере. Последнее вообще нерешаемо в вебе, и любой, кто говорит обратное, либо не разобрался, либо продаёт.

Если зайдёт, распишу отдельным постом, как искал эти восемь багов и что из этого следует про разработку в одиночку, без ревьюера за спиной.

Показать полностью 3
Отличная работа, все прочитано!

Темы

Политика

Теги

Популярные авторы

Сообщества

18+

Теги

Популярные авторы

Сообщества

Игры

Теги

Популярные авторы

Сообщества

Юмор

Теги

Популярные авторы

Сообщества

Отношения

Теги

Популярные авторы

Сообщества

Здоровье

Теги

Популярные авторы

Сообщества

Путешествия

Теги

Популярные авторы

Сообщества

Спорт

Теги

Популярные авторы

Сообщества

Хобби

Теги

Популярные авторы

Сообщества

Сервис

Теги

Популярные авторы

Сообщества

Природа

Теги

Популярные авторы

Сообщества

Бизнес

Теги

Популярные авторы

Сообщества

Транспорт

Теги

Популярные авторы

Сообщества

Общение

Теги

Популярные авторы

Сообщества

Юриспруденция

Теги

Популярные авторы

Сообщества

Наука

Теги

Популярные авторы

Сообщества

IT

Теги

Популярные авторы

Сообщества

Животные

Теги

Популярные авторы

Сообщества

Кино и сериалы

Теги

Популярные авторы

Сообщества

Экономика

Теги

Популярные авторы

Сообщества

Кулинария

Теги

Популярные авторы

Сообщества

История

Теги

Популярные авторы

Сообщества

Недвижимость и ремонт

Теги

Популярные авторы

Сообщества