Pull to refresh

CDN-провайдер Cloudflare внедрял содержимое памяти своего сервера в код произвольных веб-страниц

Reading time 4 min
Views 23K
Специалисты по безопасности из Google обнаружили неприятный баг, чем-то похожий на приснопамятную уязвимость Heartbleed в OpenSSL. Она тоже выдаёт любому желающему криптографические ключи, а также куки, пароли, содержимое POST-запросов с личными данными, кредитные карты, ключи API и другое содержимое чужих сессий.

Здесь уязвимость ограничена всего одним сервис-провайдером, пусть и таким крупным как Cloudflare. Но в определённом смысле этот баг Cloudbleed хуже, чем Heartbleed, потому что утечка данных происходит спонтанно. Эти страницы рутинно скачиваются краулерами, индексируются поисковыми системами, до сих пор хранятся в архивах веб-страниц и в кэше Google.

Cloudflare является посредником между хостером сайта и посетителями сайта, выполняя роль обратного прокси для веб-сайтов. Из-за ошибки программиста системы Cloudflare на Nginx с сентября 2016 года внедряли случайные фрагменты оперативной памяти своего сервера в содержимое веб-страниц, которое выдавалось всем пользователям.

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

Вероятно, для эксплуатации бага нужно было в течение длительного времени массово загружать страницы с сайтов, обслуживаемых Cloudflare, автоматически извлекать приватный трафик и обрабатывать его регулярными выражениями в поисках интересной информации. Это могут быть сессионные ключи, пароли, данные кредитных карт и др.


Фрагмент сессии некоего случайного пользователя Fitbit, который получили хакеры Project Zero по запросу к Cloudflare

Среди клиентов Cloudflare — такие клиенты как Uber, OK Cupid и Fitbit (всего пострадали около 4 287 625 доменов, в том числе 2ip.ru, 4pda.ru, avito.ru, diary.ru, forbes.ru, iphones.ru, javascript.ru, prlog.ru, rghost.ru, rosbalt.ru, searchengines.ru). Понятно, что в пользовательских сессиях тех же Uber, OK Cupid и Fitbit передаётся чувствительная информация о поездках пользователей, кредитных картах, маршруты поездок, личные данные о человеке с сайта знакомств, показания фитнес-трекеров и многое другое. Не говоря о миллионах других сайтов, которые сидят на Cloudflare (она контролирует примерно 5% веба, в том числе 11% сайтов из топ-10000). Это как сидеть в ресторане, где одновременно с меню официант подаёт вам часть содержимого кошелька предыдущего клиента.

Тут не угадаешь, где повезёт, так что эксплуатация предполагает массовое скачивание и обработку информации. Конечно, желательно знать, при каких условиях возникает утечка памяти. Специалистам Google удалось это выяснить случайно в результате рутинной работы по дистилляции (минимизации) корпуса страниц с целью оптимизации фаззинга, которым занимается Google.

17 февраля 2017 года сотрудник компании Google и известный хакер Тэвис Орманди (Tavis Ormandy) во время минимизации корпуса случайно наткнулся на неожиданные данные. Это был не обычный набор мусора, искажённых или неправильно маркированных данных, а нечто в таком странном формате, что Тэвис Орманди потратил время на дебаггинг, пытаясь выяснить причину ошибки минимизации, то есть ошибку в своём собственном коде. «На самом деле данные были настолько странные, что некоторые мои коллеги из отдела Project Zero тоже заинтересовались, — пишет Тэвис. — Вскоре стало ясно, что мы смотрим на фрагменты неинициализированной памяти, которые перемежаются валидными данными. Загадка разгадалась, потому что эти неинициализированные данные шли от программы, которая как раз поместила в память те данные, которые я указал. Но некоторые окружающие фрагменты имели строки и объекты, которые словно пришли от обратного прокси под управлением Cloudflare — крупнейшего провайдера CDN».

Так оно и вышло. Чуть позже исследователям удалось воспроизвести баг. Утечка информации происходила при определённом сочетании HTML-тегов на странице, которое вызывало баг на сервере Cloudflare.

Исследователи поковырялись с багом — и среди нескольких образцов получили ключи шифрования, куки, пароли, фрагменты POST-форм и данные HTTPS-запросов других пользователей. Как только они увидели это, то немедленно прекратили эксплуатацию бага и сразу сообщили о нём в компанию Cloudflare.

Тэвис Орманди предполагает, что баг Cloudflare связан с функцией ScrapeShield, которая работает у них на серверах — она парсит и обфусцирует HTML. Сама компания Cloudflare позже подтвердила, что проблема действительно была с парсером, который обфусцирует почту, делает Server Side Excludes и Automatic HTTPS Rewrites. Баг закрался примерно год назад, когда этот парсер, написанный на Ragel, оптимизировали и внедрили как модуль Nginx. Теперь выяснилось, что ошибка указателя и перерасход буфера в парсере присутствовали много лет, просто раньше не происходила утечка памяти.

/* generated code */
if ( ++p == pe )
    goto _test_eof;

Вот как парсер из-за бага обрабатывал атрибут в теге <script>.

script_consume_attr := ((unquoted_attr_char)* :>> (space|'/'|'>'))
>{ ddctx("script consume_attr"); }
@{ fhold; fgoto script_tag_parse; }
$lerr{ dd("script consume_attr failed");
       fgoto script_consume_attr; };

Орманди говорит, что этот баг хуже Heartbleed в том смысле, что пользователю не нужно совершать целенаправленный запрос, чтобы прочитать фрагмент памяти сервера. Здесь секретная информация принудительно выдаётся в его браузер. Большинство людей просто не поймут, что это такое. Но эти страницы скачиваются краулерами, индексируются поисковыми системами. В случае Heartbleed такой утечки данных не было — там надо было отправлять специальный запрос серверу, где работает OpenSSL.

Как обычно, через 90 дней Google опубликует информацию из баг-репорта, способ воспроизвести баг и искомое сочетание HTML-тегов, но Cloudflare уже закрыла уязвимость. Хотя они не отреагировали на письма и баг-репорт, но в течение часа заметили призыв Тэвиса в твиттере.


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

Вчера компания Cloudflare опубликовала отчёт с детальным описанием инцидента. Она сразу предупредила, что утечки пользовательских SSL-ключей не произошло, поскольку SSL-соединения всегда терминируются на изолированной машине с Nginx, которая не была подвержена этому багу.
Tags:
Hubs:
+33
Comments 43
Comments Comments 43

Articles