Об одной уязвимости в…

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.


Год назад, 21 марта 2019, в баг баунти программу Mail.Ru на HackerOne пришел очень хороший багрепорт от maxarr. При внедрении нулевого байта (ASCII 0) в POST-параметр одного из API-запросов веб-почты, который возвращал HTTP-редирект, в данных редиректа виднелись куски неинициализированной памяти, в которых чаще всего раскрывались фрагменты из GET-параметров и заголовков других запросов к тому же серверу.

Это критическая уязвимость, т.к. запросы содержат в том числе сессионные куки. Через несколько часов был сделан временный фикс, который фильтровал нулевой байт (как потом выяснилось, этого было недостаточно, т.к. оставалась возможность инъекции CRLF /ASCII 13, 10, что позволяет манипулировать заголовками и данными HTTP-ответа, это менее критично, но все равно неприятно). Одновременно с этим проблема была передана аналитикам безопасности и разработчикам для поиска и устранения причин возникновения бага.

Почта Mail.ru — это очень непростое приложение, в формировании ответа может участвовать большое количество различных фронтенд/бекенд-компонентов, как опенсорсных (большое спасибо всем разработчикам свободного ПО), так и собственной разработки. Удалось исключить все компоненты кроме nginx и openresty и локализовать проблему до вызова ngx.req.set_uri() в OpenResty-скрипте, который вел себя не так, как ожидалось (воткнуть нулевой байт или перевод строки через GET-параметры с rewrite в ngx_http_rewrite_module, который, согласно документации используется и, казалось бы, должен работать абсолютно аналогично не получится). Были устранены возможные последствия, добавлена максимально строгая фильтрация и было проверено, что фильтрация устраняет все возможные векторы. Но механизм, который приводил к утечке содержимого памяти так и остался загадкой. Через месяц багрепорт закрыли как разрешенный, а разбор причин возникновения бага отложили до лучших времен.

OpenResty — это весьма популярный плагин, позволяющий писать Lua-скрипты внутри nginx, и он используется в нескольких проектах Mail.ru, поэтому проблема не считалась решенной. И спустя некоторое время к ней все-таки вернулись, чтобы понимать истинные причины, возможные последствия и составить рекомендации для разработчиков. В раскопках исходного кода участвовали Денис Денисов и Николай Ермишкин. Выяснилось что:

  • Nginx защищает GET-параметры от инъекции служебных символов и дает возможность использовать в rewrite только GET-параметры. Поэтому эксплуатировать инъекцию через контролируемые пользователем параметры в nginx не получается. POST параметры при этом не защищены. OpenResty позволяет работать и с GET и с POST параметрами, поэтому при использовании POST параметров через OpenResty появляется возможность инъекции специальных символов.
  • В nginx при использовании rewrite с пользовательскими данными есть возможность directory traversal (и вероятно SSRF) в некоторых конфигурациях, но это известный факт, и он должен обнаруживаться статическими анализаторами конфигураций в Nginx Amplify и Gixy от Яндекс (да, мы его тоже используем, спасибо). При использовании OpenResty такую возможность легко пропустить, но нашу конфигурацию это не затрагивало.
  • В nginx есть ошибка, приводящая к утечке содержимого памяти, если строка rewrite содержит нулевой байт. При отдаче редиректа nginx выделяет новый буфер памяти, соответствующий полной длине строке, но копирует туда строку через строчную функцию, в которой нулевой байт является терминатором строки, поэтому строка копируется только до нулевого байта, остаток буфера содержит неинициализированные данные. Подробный разбор можно найти здесь.

Дальнейшая реакция


О проблеме сообщили разработчикам nginx и OpenResty, разработчики не рассматривают проблему как ошибку безопасности в nginx, т.к. в самом nginx нет возможности эксплуатации ошибки через инъекцию спецсимволов, фикс раскрытия содержимого памяти был опубликован 16 декабря. За 4 месяца с момента репорта в OpenResty так же не было сделано каких-либо изменений, хотя было понимание, что необходим безопасный вариант функции ngx.req.set_uri(). 18 марта 2020 мы опубликовали информацию, 21 марта OpenResty выпустила версию 1.15.8.3, которая добавляет проверку URI.

Portswigger написал хорошую статью и взял комментарии у OpenResty и Nginx (правда комментарий о том, что раскрывается только небольшой фрагмент памяти является неверной и вводит в заблуждение, это определяется длиной строки, следующей за нулевым байтом и, при отсутствии явных ограничений на длину может контролироваться атакующим).

Так в чем же была ошибка и что делать, чтобы ее предотвратить?


Была ли ошибка в nginx? Да, была, потому что утечка содержимого памяти это в любом случае ошибка.

Были ли ошибка в OpenResty? Да, как минимум не был исследован и документирован вопрос о безопасности предлагаемой OpenResty функциональности.

Была ли допущена ошибка конфигурации / использования OpenResty? Да, потому что в отсутствии явного указания, было сделано непроверенное предположение о безопасности используемой функциональности.

Какая из этих ошибок является уязвимостью безопасности с баунти на $10000? Для нас это в общем-то не важно. В любом ПО, особенно на стыке нескольких компонент, особенно предоставляемых разными проектами и разработчиками никто и никогда не может гарантировать, что все особенности их работы известны и документированы и отсутствуют ошибки. Поэтому любая уязвимость безопасности возникает именно там, где она влияет на безопасность.

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

Errata


По опыту предыдущей статьи, ради сохранения чистоты языка:

баг баунти — конкурс охоты за ошибками
багрепорт — уведомление об ошибке
редирект — перенаправление
опенсорсный — с открытым кодом
errata — работа над ошибками
Источник: https://habr.com/ru/company/mailru/blog/493920/


Интересные статьи

Интересные статьи

DIY, как говорит Википедия, это уже давно субкультура. В этой статье хочу рассказать о своем diy проекте небольшого беспроводного мультисенсорного датчика, и это будет моим небольшом ...
Выдача сертификатов началась 16 сентября прошлого года. С тех пор было опубликовано немало статей и заметок о новом стандарте беспроводной связи, в том числе, и на Хабре. Большин...
В прошлый раз мы делали подборку литературы о тонкостях работы хакеров и рисках в ИТ. Сегодня продолжаем развивать эту тему. Под катом: история Cult of the Dead Cow — группировки из 80-х, которая...
Небольшой сказ о маленькой погрешности, с помощью которой был получен доступ ко всем платным курсам и домашним заданиям на ресурсах. А так же немного о других найденных уязвимостях. ...
В конце марта 2019 года американская компания Trustwave, занимающаяся кибербезопасностью и сервисами по защите от угроз, опубликовала сообщение об уязвимости в СУБД PostgreSQL, которая присутст...