- PVSM.RU - https://www.pvsm.ru -

Год назад, 21 марта 2019, в баг баунти программу Mail.Ru [1] на HackerOne пришел очень хороший багрепорт [2] от maxarr [3]. При внедрении нулевого байта (ASCII 0) в POST-параметр одного из API-запросов веб-почты, который возвращал HTTP-редирект, в данных редиректа виднелись куски неинициализированной памяти, в которых чаще всего раскрывались фрагменты из GET-параметров и заголовков других запросов к тому же серверу.
Это критическая уязвимость, т.к. запросы содержат в том числе сессионные куки. Через несколько часов был сделан временный фикс, который фильтровал нулевой байт (как потом выяснилось, этого было недостаточно, т.к. оставалась возможность инъекции CRLF /ASCII 13, 10, что позволяет манипулировать заголовками и данными HTTP-ответа, это менее критично, но все равно неприятно). Одновременно с этим проблема была передана аналитикам безопасности и разработчикам для поиска и устранения причин возникновения бага.
Почта Mail.ru — это очень непростое приложение, в формировании ответа может участвовать большое количество различных фронтенд/бекенд-компонентов, как опенсорсных (большое спасибо всем разработчикам свободного ПО), так и собственной разработки. Удалось исключить все компоненты кроме nginx и openresty и локализовать проблему до вызова ngx.req.set_uri() [4] в OpenResty-скрипте, который вел себя не так, как ожидалось (воткнуть нулевой байт или перевод строки через GET-параметры с rewrite в ngx_http_rewrite_module, который, согласно документации используется и, казалось бы, должен работать абсолютно аналогично не получится). Были устранены возможные последствия, добавлена максимально строгая фильтрация и было проверено, что фильтрация устраняет все возможные векторы. Но механизм, который приводил к утечке содержимого памяти так и остался загадкой. Через месяц багрепорт закрыли как разрешенный, а разбор причин возникновения бага отложили до лучших времен.
OpenResty — это весьма популярный плагин, позволяющий писать Lua-скрипты внутри nginx, и он используется в нескольких проектах Mail.ru, поэтому проблема не считалась решенной. И спустя некоторое время к ней все-таки вернулись, чтобы понимать истинные причины, возможные последствия и составить рекомендации для разработчиков. В раскопках исходного кода участвовали Денис Денисов [5] и Николай Ермишкин [6]. Выяснилось что:
О проблеме сообщили разработчикам nginx и OpenResty, разработчики не рассматривают проблему как ошибку безопасности в nginx, т.к. в самом nginx нет возможности эксплуатации ошибки через инъекцию спецсимволов, фикс раскрытия содержимого памяти [9] был опубликован 16 декабря. За 4 месяца с момента репорта в OpenResty так же не было сделано каких-либо изменений, хотя было понимание, что необходим безопасный вариант функции ngx.req.set_uri(). 18 марта 2020 мы опубликовали информацию, 21 марта OpenResty выпустила версию 1.15.8.3 [10], которая добавляет проверку URI.
Portswigger написал [11] хорошую статью и взял комментарии у OpenResty и Nginx (правда комментарий о том, что раскрывается только небольшой фрагмент памяти является неверной и вводит в заблуждение, это определяется длиной строки, следующей за нулевым байтом и, при отсутствии явных ограничений на длину может контролироваться атакующим).
Была ли ошибка в nginx? Да, была, потому что утечка содержимого памяти это в любом случае ошибка.
Были ли ошибка в OpenResty? Да, как минимум не был исследован и документирован вопрос о безопасности предлагаемой OpenResty функциональности.
Была ли допущена ошибка конфигурации / использования OpenResty? Да, потому что в отсутствии явного указания, было сделано непроверенное предположение о безопасности используемой функциональности.
Какая из этих ошибок является уязвимостью безопасности с баунти на $10000? Для нас это в общем-то не важно. В любом ПО, особенно на стыке нескольких компонент, особенно предоставляемых разными проектами и разработчиками никто и никогда не может гарантировать, что все особенности их работы известны и документированы и отсутствуют ошибки. Поэтому любая уязвимость безопасности возникает именно там, где она влияет на безопасность.
В любом случае, хорошей практикой будет нормализовать или максимально ограничивать/фильтровать входные данные, которые уходят в любой внешний модуль/API, если нет явных указаний и однозначного понимания, что этого не требуется.
По опыту предыдущей статьи [12], ради сохранения чистоты языка:
баг баунти — конкурс охоты за ошибками
багрепорт — уведомление об ошибке
редирект — перенаправление
опенсорсный — с открытым кодом
errata — работа над ошибками
Автор: Владимир Дубровин
Источник [13]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/nginx/350926
Ссылки в тексте:
[1] баг баунти программу Mail.Ru: https://hackerone.com/mailru
[2] багрепорт: https://hackerone.com/reports/513236
[3] maxarr: https://hackerone.com/maxarr
[4] ngx.req.set_uri(): https://github.com/openresty/lua-nginx-module#ngxreqset_uri
[5] Денис Денисов: https://hackerone.com/kpebetka
[6] Николай Ермишкин: https://hackerone.com/yngwie
[7] Nginx Amplify: https://www.nginx.com/products/nginx-amplify/
[8] Gixy: https://github.com/yandex/gixy
[9] раскрытия содержимого памяти: https://hg.nginx.org/nginx/rev/02a539522be4
[10] версию 1.15.8.3: https://github.com/openresty/openresty/compare/v1.15.8.2...v1.15.8.3
[11] написал: https://portswigger.net/daily-swig/email-security-mail-ru-patches-critical-memory-disclosure-flaw
[12] предыдущей статьи: https://habr.com/en/company/mailru/blog/492094/
[13] Источник: https://habr.com/ru/post/493920/?utm_source=habrahabr&utm_medium=rss&utm_campaign=493920
Нажмите здесь для печати.