Pull to refresh

Comments 31

выставили авторизационную куку на домен второго уровня, а на серверной стороне стали проверять корректность переданной куки.

Кто-нибудь может объяснить, как делается серверная проверка? Предположим, у меня есть 2 сервера, один в России + ещё один в Германии. Как безопасно организовать процесс, какие технологии использовать?
P.S. Если это в блоге уже описывалось, буду рад ссылке, вопрос интересует, но в сетевых технологиях не силён.
Правильно сделать так, чтобы код, который обслуживает запросы пользователей, и код, который производит авторизацию запросов и работает с эккаунтами пользователями были изолированы друг от друга. Изоляция может быть в рамках одной машины, если это небольшой проект — разнести его по разным виртуальным хостам, системным эккаунтам, возможно, виртуальным машинам. В случае двух сильно удаленных хостов с негарантируемой связью это единственный вариант. Если проект большой — то чем больше уровней изоляции — тем лучше — т.е. желательно разносить не просто по разным виртуальным хостам, системным эккаунтам — но и по разным физическим машинам и сегментам сети.

Если вопрос о том, как безопасно связать 2 сервера — то ответ: через VPN.
куку просто надо подписывать одним ключем, который секретно храниться на двух серверах. Посмотрите как это реализовано в asp.net «из коробки» msdn.microsoft.com/en-us/library/ff649308.aspx
Ну и проверять пришедшую куку перед какой-то с ней работой естественно.
В mail.ru когда-то использовался похожий подход, но отказались от него довольно давно, хотя для многих проектов он вполне пригоден. Единственное замечание — с точки зрения разделения доступа использование симметричного ключа является ошибкой, т.к. ключ компрометируется при компрометации любого хоста. Правильно использовать ассиметричную криптографию или комбинацию.

Но у такого подхода есть и свои недостатки, например, достаточно сложно завершить сеанс пользователя на всех проектах одновременно.
Хороший пост. Раскрыта тема применения флагов Secure и HttpOnly. Надо взять себе на вооружения.
Спасибо, отличный пост. Must read всем причастным
> Mail.Ru — огромный портал, существующий более 15-ти лет. За это время мы прошли путь от небольшого веб-проекта до самого посещаемого сайта рунета.
vk.com?
vk.com действительно самый посещаемый сайт рунета, но не портал. Mail.Ru это не только главная страница или почта — это несколько сотен проектов. Месячная аудитория портала Mail.Ru – 59 млн. Для сравнения: ВКонтакте, — 52,1 млн (TNS, все население России в возрасте от 12 до 64 лет, март 2014 г.) и он только третий.
Я подумал, что Mail.Ru в какой-то момент был самым посещаемым сайтом рунета.
Спасибо за статью, возьму на заметку. Возник вопрос, не проще ли полностью поставить все проекты за принудительный HTTPS.
Очень правильный вопрос, спасибо.

Принудительный HTTPS (перенаправление + HTTP Strict Transport Security) обязательно нужен на критичных проектах, но он не отменяет необходимости реализовывать разделение сессий, потому что:
  • Без разделения сессий компрометация одного из проектов приведет к компрометации всех проектов. В качестве примера можно привести Heartblead. Несколько проектов у нас были поддвержены этой атаке. По счастью, почту и центр авторизации «пронесло». Это как раз тот случай, когда нас спасло разделение сессий, т.к. компрометация второстепенных проектов не привела к компрометации учетных записей пользователей и почты.
  • Если у кук нет флажка HTTPOnly, то XSS приводит к угону сессии, наличие https никак не влияет на это
  • HTTP Strict Transport Security работает не во всех браузерах + не работает, когда пользователь долго не заходил на сайт.
    Если у куки нет флажка Secure, то MitM все равно может угнать куку, заставив пользователя посетить незащищенный сайт, т.к. в запросе на незащищенный сайт кука будет присутствовать. Принудительный HTTPS в данном случае тоже не спасет.

Т.е. надо использовать И принудительный https И разделение сессий.
Зависит от проекта.
Там, где отдается много аудио/видео/больших картинок, будут очень большие накладные расходы на шифрование.
Как на серверах, так и на клиентах (а особенно на мобильных клиентах).
Т.е. вылезают проблемы из другой области.
Накладные расходы есть, но при правильной организации их можно минимизировать. Мы тоже боялись что не справимся по нагрузкам, но на практике потребление ресурсов оказалось не таким страшным. Вот здесь статья, как почта переводилась на SSL.
SSL используется и в Облаке, где трафик передается десятками гигабайт, в том числе в мобильных клиентах, к явным проблемам с быстродействием это не приводит.
Понятно, спасибо.
Честно говоря, я думал, у вас https терминируется каким-нибудь аппаратным решением :)
Мне кажется, серьёзные проблемы должны возникнуть при передаче видео, в том же HD.
Даже не столько у вас, сколько у клиента.
Если не секрет, как вы с видео поступили?
Поддержка «онлайнового» просмотра загруженного видео пока только в разработке, но могу сказать что потребление процессора на нужды SSL не превышает 2%, на мобильных клиентах процент может быть немного выше, но все равно не критический.
Очень полезно. Интересно было бы сравнить с авторизацией у гугл: как они это делают, какие плюсы/минусы.
Деталей реализации не знаю, но гугл совершенно точно использует разделение сессий по поддоменам.
Мне больше понравилась реализация на vk.com. Там основная кука сессии привязана к ip. Если украсть её, то она окажется бесполезна. В случае смены ip, происходит редирект на домен 3-го где установлена http only, secure кука, в случае её успешной проверки происходит обновление ip-зависимой куки. Вообще удивило что такой большой портал как mail.ru так поздно занялся решением такой большой проблемы.
Это почти тот же интересный и правильный вопрос, что обсуждался чуть выше, про то, что не проще ли внедрить принудительный https. Таким образом vk.com решается проблему относительно безопасного использования сессионных кук на небезопасном сайте без поддержки . Это в общем-то костыль, решение не надежно — если у вас в интернет-кафе отснифили привязанную к IP куку, то пока вы сидите в кафе и даже когда вы из кафе уходите, у похитителя остается доступ к сайту вместе с вашим прошлым IP адресом. Конечно, через некоторое время эта сессия проэкспайрится, но до тех пор ваш эккаунт доступен.
В почте Mail.Ru эта проблема решается именно путем принудительного https и HSTS, что гораздо надежней. vk.com уже внедряет https на добровольной основе и, надеюсь, в итоге придет к тому же решению с принудительным https + HSTS.

В этой же статье описывается решение несколько другой проблемы, с которой ВКонтакте пока не приходилось сталкиваться: это наличие в рамках одного домена второго уровня большого количества разных проектов, между которыми разделяется общая аутентификация пользователя. Требуется, чтобы ошибка в менее критическом проекте, например флеш-открытке с котиками, не затрагивала безопасность критических проектов, например ПочтыMail.Ru.
Видимо я что-то упускаю. А что в текущей реализации мешает использовать XSS на проекте X про следующему сценарию:
1. Скрытый фрейм грузит главную проекта x.mail.ru — прозрачно для пользователя проходит авторизация, если раньше ее не было.
2. Скрытый фрейм запускает с помощью XSS shell of the future, обходя ограничения http only, а secure здесь и так никаким боком.
3. Злоумышленники делают то, что хотели — читают логин с полученной страницы, крадут данные, что-то меняют и т.п.

Или же речь только о том, что теперь XSS на одном проекте не даст доступа к остальным?

К стати, а почему бы не сделать Google-style авторизацию на новых, ранее не посещенных, проектах — по обязательному клику со стороны пользователя? Тогда ни разу не ходившие на x.mail.ru окажутся неподверженны XSS на нем.
Если по пунктам:
1й — не получится из-за X-Frame-Options на главной странице.
2й — shell of the future не обходит ограничения HTTPOnly, это реверс-шел на JS и имеет доступ только к тому, к чему имеет доступ JS. JS не имеет доступа к HTTPOnly кукам. Кроме того, загрузить внешний скрипт на наших основных проектов может быть немного сложно из-за CSP (Content Security Policy).
3й — НО, даже если полуилось загрузить скрипт и даже если бы скрипт имел доступ к кукам на главной странице, для того, чтобы получить доступ к сессии электронной почты, не достаточно куки с главной страницы, это как раз заслуга разделения сессий. Чтобы получить доступ к электронной почте, XSS должен быть именно в электронной почте.

И кстати, у нас есть программа поиска уязвимостей, за XSS в почте мы платим около $500, присоединяйтесь.
1-й X-Frame-Options это действительно похвально, но скрытый фрейм нужен только для того, чтобы пользователь не слишком сильно насторожился. Делаем тоже самое в открытую в новой вкладке, пускай насторожится, все равно поздно будет. X-Frame-Options это скорее против clikjacking.
2-й Shell of the future это в каком-то смысле обход HTTPOnly. Потому что не нужно узнавать само значение из куки, как было принято 15 лет назад и как до сих пор учат чуть ли не все гайды «XSS для начинающих». Просто шлем запросы из пользовательского браузера и читаем ответы. Само собой в реальных атаках SoF не используется, пишутся конкретные скрипты, которые без интерактивного участия проводят атаку, но суть остается та же — куки красть не надо.
А вот CSP, хоть и не панацея, но, по-моему, является на данный момент самым серьезным механизмом противодействия XSS. HTTPOnly и даже хромовский XSS аудитор проблему не решают, а CSP при правильных настройках сводит практически к нулю вероятность успешной атаки. Молодцы, что используете.
3-й Я уже осознал, что речь как раз о «XSS на a.mail.ru не дает доступа к b.mail.ru», по вашим предыдущим ответам :)

Программу поиска видел, как только руки дойдут — так сразу.
Да, все так, в этом плане XSS это действительно в какой-то степени эквивалент доступа к сессии пользователя (не важно, с кукой или без), на то время, пока открыта вкладка.
Да совершенно верно. Выше обсуждался вариант, который еще более похож на Kerberos, когда клиент получает подписанную куку.
Расскажите, пожалуйста, подробнее вот про это:
Когда пользователь заходит на сайт проекта, для которого у него еще нет авторизации, его запрос перенаправляется в центр авторизации. Центр авторизации аутентифицирует его по наличию куки .auth.mail.ru, генерирует одноразовый токен и перенаправляет на страницу проекта. Токен проксируется проектом в центр авторизации, который по нему генерирует уже проектную куку для .project.mail.ru.


Не очень понял логику. Зачем «Токен проксируется проектом в центр авторизации, который по нему генерирует уже проектную куку для .project.mail.ru»? Токен проксируется обратно на auth.mail.ru для того чтобы убедиться, что это валидный токен, верно? Но почему куку генерирует центр авторизации, а не сам project.mail.ru? Ведь, насколько я понял, задача в том, чтобы выставить sdc-куку именно на уровне проекта. И если кука генерируется на уровне центра авторизации, то как она передается на сайт проекта? Грубо говоря: проект curl-ом соединяется с центром авторизации, а центр авторизации возвращает некторое значение, которое проект должен использовать для sdc-куки?

И еще вопрос: как запрос проекта «проксируется» в центр авторизации? Это curl-запрос не выходящий за рамки локальной сети, в которой работают все проекты или нет?
Можно и curl, но на самом деле проще даже без курла — именно проксированием запроса (+служебные заголовки, например для передачи информации о клиенте, токена авторизации проекта и т.п.) и ответа — например балансировщиком или на reverse proxy. Центр авторизации в таком случае отвечает и за валидацию токена и за то, чтобы он был одноразовым. Это позволяет избежать лишнего дублирующего кода в проектах.

Как вариант, можно подписывать токен, но тогда логику проверки придется реализовывать в каждом проекте.
Спасибо. Уточните, пожалуйста, еще один момент.

Когда пользователь заходит на сайт проекта, для которого у него еще нет авторизации, его запрос перенаправляется в центр авторизации.


Где определяется, что пользователь не авторизован? В браузере или на сервере?

Если речь о редиректе на уровне веб-сервера, то какой код для редиректа используется? 305, 307? Или авторизационная кука sdc-кука проверяется джаваскриптом (она ведь не httponly?) в браузере и им же делается редирект?
Проверяется на серверсайде, дается обычно 302 с запретом кэширования.
Спасибо большое за ответ. Еще один вопрос.

Центр авторизации аутентифицирует его по наличию куки .auth.mail.ru, генерирует одноразовый токен и перенаправляет на страницу проекта.

Я правильно понимаю, что токен передается просто GET-параметром на какой-то стндартный для проекта redirect url (примерно также сделано в oAuth2)? То есть схема выглядит так:
* юзер зашел на project.mail.ru, при этом он уже залогинен на одном из других проектов Mail.ru,
* его редиректит (с кодом 302) на auth.mail.ru,
* так как в auth.mail.ru есть его авторизационная кука его редиректит на, например, project.mail.ru/redirect?token=123456,
* project.mail.ru берет токен и передает его обратно на auth.mail.ru и в ответ получает сообщение, что все ок, токен валиден,
* после этого project.mail.ru выставляет свою авторизационную куку.

Верно я понял или нет?
Only those users with full accounts are able to leave comments. Log in, please.