Работа над ошибками: отчет IT-отдела команды Навального
21 июля хабра-пользователь grumpysugar опубликовал статью о найденной им уязвимости в инфраструктуре нашей команды. Уязвимость действительно существовала, и мы ее устранили. Но если вы видите информацию о новых утечках из нашей базы данных, знайте, что это с высокой вероятностью обычный вброс. В этом посте мы объясняем, почему.
Сразу хотим отметить, что пользователь заблаговременно с нами связался через саппорт месяц назад. Мы эскалировали проблему, устранили ее в первые же минуты после обнаружения и отправили пользователю ответным письмом благодарность и отчет о произошедшем.
Во время работ по инфраструктуре была допущена ошибка, и дашборд Kubernetes WebView, который наша команда разработки использует для отладки приложений, стал доступен по одному из наших известных почтовых доменов (на самом деле все домены, которые ресолвились в этот IP-адрес, но не имели своего сервиса, попадали на Kubernetes WebView, потому что он стал default backend).
Ошибка была допущена буквально в одной строчке yaml-конфига. В настройках было явно не объявлено поле host, которое ограничило бы, на каком хостнейме работает сервис. В связи с этим сервис оказался доступным на хосте, который явно был не перечислен в других сервисах.
rules:
- host: # <-- обратите внимание на пустую строку здесь
http:
paths:
Из-за этого сервис стал доступен по адресу rus.vote и нескольким другим, которые ресолвились на тот же IP-адрес.
--- a/kube-web-view/templates/ingress.yaml
+++ b/kube-web-view/templates/ingress.yaml
@@ -27,7 +27,7 @@ spec:
{{- end }}
rules:
{{- range .Values.ingress.hosts }}
- - host: {{ .name }}
+ - host: {{ .host }}
http:
paths:
- path: {{ default "/" .path }}
В первые часы после остановки сервиса были заменены секреты, использующиеся в приложениях, заменены пароли от баз данных и адреса кластера, а допустивший ошибку девопс-инженер был отстранен от работы. Мы не расцениваем его действия как злой умысел, но расцениваем как ошибку. Само собой, ни один сотрудник не использовал этот дашборд по данному публичному адресу. Для разработчиков доступ в Kubernetes Webview был представлен на другом техническом url через корпоративный VPN и базовую авторизацию.
В логах действительно можно было отследить регистрирующиеся почтовые адреса. Однако обратиться напрямую к базе и скачать адреса, не отобразившиеся в логах (включая все старые адреса, которые регистрировались до появления уязвимости), не представлялось возможным. Логи имели определенный жизненный цикл и само собой пропадали при истечении жизни подов.
Инфраструктурные работы, из-за которых эта проблема возникла, проводились в связи с последней атакой на нас с использованием ключа Mailgun, который по нашей оплошности оставался у бывшего сотрудника, менеджера рассылок. Мы меняли настройки Kubernetes Webview, принципы хранения секретов. Но из-за большого количества проектов и большого объема ручной работы не до всех «успели добраться». Поэтому данные о них отобразились в открывшемся дашборде.
# ирония: MAILGUN_API_KEY: 3***1d
По его формату можно было заметить, что он имеет тип sending-key (не позволяющий читать логи и выкачивать почты, по которым были отправлены письма), — это значит, что мы уже успели сделать вывод из нашей предыдущей ошибки, но не успели к тому моменту перетащить секреты проекта в надежное место.
У пользователя, обратившего внимание на уязвимость, тем не менее, остались вопросы о проделанной нами работе над ошибками. Аналогичные вопросы остались и после нашего отчета-расследования об утечке API-ключа Mailgun через нашего бывшего сотрудника, где мы детально рассказали, как именно был организован перехват почт: показали IP-адреса, входы с них в корпоративную почту, примеры запросов и подтвердили идентичность исполняемого скрипта при помощи фингерпринтинга.
Что было сделано помимо расследования, чтобы минимизировать риски повторения подобных инцидентов:
Мы пересмотрели политику безопасности организации и хранения секретов (мы больше не храним ни один секрет в k8s configmap, а только в secrets), их шифрования и доступа к управлению ими. Доступ к секретам имеет ограниченное количество сотрудников, ведутся аудит-логи. В связи со скоростью выпуска проектов и ограниченным штатом разработчики ранее имели доступ к тем секретам, что использовались в продакшене. Сейчас — нет.
Мы перевели проекты, использующие сервис Mailgun, на так называемые sending keys, с помощью которых невозможно смотреть логи, даже если эти ключи по каким-то причинам окажутся в руках неавторизованных лиц. К сожалению, из-за большого объема проектов, которые команда Навального выпускала за свою историю, этот процесс пришлось осуществлять в ручном режиме, так как автоматики не имелось.
Помимо базовых авторизаций и использования VPN для доступа к ресурсам для внутреннего пользования мы приняли решение перевести все внутренние сервисы на немаршрутизируемые адреса, изолировав их от внешнего интернета на сетевом уровне, и использовать Google Cloud VPN со строгими политиками аутентификации и авторизации, включающими в себя обязательное использование 2FA. На уровне политики безопасности Google Apps мы обязываем всех сотрудников пользоваться двухфакторной аутентификацией.
Мы ввели дополнительное ревью при выпуске проекта — со стороны как девопс-инженеров, так и разработчиков. Выбор технологии под необходимую задачу утверждается несколькими ревьюерами (зачастую это девопс-инженеры и старшие разработчики).
Понимаем, что после допущенных нами ошибок доверие к нашей технической команде резко упало. Уже почти каждую неделю в анонимных (и не очень) телеграм-каналах мы видим сообщения о якобы «утечке» адресов базы УМГ. Подобные выгрузки не имеют ничего общего с действительностью. Да, мы понимаем, что часть email-адресов, введенных на сайте Умного голосования, также была похищена злоумышленником через утекший ключ Mailgun, но тем не менее, анализируя подобные «базы», мы видим крайне низкое пересечение с нашей реальной базой. Имея доступ к ней, злоумышленники могли бы выложить не только почту, но и фактический адрес, указанный на сайте. Ни из каких «логов» вытащить это было нельзя.
В последнее время мы видим множество создаваемых зеркал — полных аналогов сайта Умного голосования, на которых людей приглашают к регистрации. Мы научились их отслеживать и благодаря работе Общества Защиты Интернета стараемся отправлять запросы на их блокировку. Очевидно, что эти сайты создаются для дискредитации проекта и для того, чтобы в день выборов ввести пользователей в заблуждение. Базы, которые называют сливом базы УМГ, явно пополняют в том числе и регистрациями с них. Пользователь помнит, что регистрировался на сайте, похожем на настоящий сайт, но не подозревает, что этот сайт не наш.
Честно скажем, IT-отдел команды Навального не обошли стороной и события, связанные со сфабрикованным «делом об экстремизме». Нам пришлось расстаться со всем штатом и некоторыми волонтерами, которые работали над проектами. Кого-то вызывали на допрос, и даже не единожды.
Мы в очередной раз строим команду практически с нуля, нам заново нужно организовывать работу с волонтерами, и нам не хватает технической экспертизы.
Когда-то мы были совсем маленькие, буквально с одним техническим сотрудником и условным менеджером рассылок (немного разработчиком, который умеет программировать и знает API-ключ), затем с небольшим штатом фронтенд- и бекенд-разработчиков. Сейчас же количество проектов и скорость их выпуска несравнимо возросли.
За последний год мы привыкли к следующему стеку:
На фронте — React (Next.js).
На бэкенде в основном Python (Django и немного aiohttp). Небольшое количество легковесных микросервисов делалось под задачу на Golang, но в 90% случаев мы все еще работаем с Python. Базы данных — PostgreSQL и SQLite. А еще ElasticSearch там, где нужно горизонтальное масштабирование базы данных.
На девопс-стороне работаем с Kubernetes — он позволяет нам эффективно бороться с DDoS, экономить ресурсы, пока трафика мало, быстро масштабироваться, если приходит нагрузка (будь то от публикации или от атаки), и безопасно выкатывать новые версии программного обеспечения. Но главное — за все время работы у команды накопилось большое количество сервисов, и именно этим в первую очередь объясняется то, что мы используем такие непростые технологии, как Kubernetes.
Ни один проект не обходится без IT-проджект-менеджера, тестировщика, команды дизайна (работаем с Figma).
В качестве ci/cd используем Gitlab, в качестве таск-менеджера — Youtrack, для коммуникации — Slack.
Кроме веба, у нас еще есть приложение «Навальный» в AppStore и Google Play — в нем работают рекомендации Умного голосования (в день выборов) и блог Навального (постоянно). В приложение встроена защита от блокировок Роскомнадзора, поэтому мы возлагаем на него особые надежды и будем развивать его дальше. Приложение работает на Kotlin Multiplatform Mobile + нативные фронтенды на Android и на iOS.
Инцидент, когда бывший сотрудник с помощью API-ключа получил доступ к логам отправок регистрационных писем из базы сайта «Свободу Навальному», мы расследовали. Этот же злоумышленник похищал email-адреса наших сторонников из Петербурга — вероятно, это было связано с его личным политическим проектом. Но все последующие сообщения об утечках базы Умного голосования — это не более чем попытки дискредитировать проект.
Мы признаем ошибку с публичной доступностью внутреннего сервиса. Мы установили ее причины и исправили ее, предприняли технические и организационные меры, чтобы устранить целые классы возможных проблем безопасности. Мы очень надеемся на вашу поддержку и постараемся заслужить ваше доверие вновь.
Связаться с нами вы можете, написав на почту dev@navalny.com
Или заполнив анкету IT-волонтера команды Навального