В этой статье мы поговорим о баге в Apache Tomcat, популярнейшем веб-сервере для сайтов на Java. Баг позволяет загружать любые файлы на сервер, так что, загрузив файл JSP, можно добиться выполнения произвольного кода. Разберемся, как работает эта уязвимость.
 

Общая информация

Наряду с Apache Struts 2, уязвимость в котором мы разбирали в прошлой статье, под раздачу багов попал и веб-сервер Tomcat. За последнее время было найдено сразу несколько уязвимостей.

19 сентября команда разработчиков в очередной рассылке официально подтвердила наличие и успешный фикс двух уязвимостей, которые получили статус критических. Первая значится под номером CVE-2017-12615. После того как ее запатчили, сразу же нашелся способ обойти заплатку (CVE-2017-12616), и последовал новый фикс. Не поверишь, но вскоре обошли и его — уязвимость носит номер CVE-2017-12617, и ее общий смысл сводится к тому, что неавторизированный пользователь, манипулируя именем файла в PUT-запросе, может создать JSP-файл с произвольным содержимым. Уязвимости подвержены все ветки, начиная с 5.x и заканчивая 9.x.

WARNING

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

 

Стенд

Сначала, как водится, поднимаем тестовый стенд. Я буду использовать версии Tomcat для Windows, так как CVE-2017-12615 и CVE-2017-12616 касаются только их.

Для проверки уязвимостей можно использовать любую из версий — 7.0.81, 8.5.20 или 9.0.0.M26. Все они уязвимы.

Также ты всегда можешь использовать Docker, благо у Apache есть официальный репозиторий, из которого можно поднять любую версию Tomcat одной командой.

docker run -it --rm -p 8888:8080 tomcat:7.0.81

Теперь на порте 8888 у тебя обитает выбранная версия веб-сервера.

После успешного запуска нужно отредактировать конфигурационный файл web.xml и добавить в него вот такие строки.

        <init-param>
​            <param-name>readonly</param-name>
​            <param-value>false</param-value>
        </init-param>

Они идут в этот раздел:

    <servlet>
        <servlet-name>default</servlet-name>

Таким образом мы выключаем параметр readonly, что позволяет использовать запросы PUT и DELETE. Но простое включение этой опции, конечно же, не открывает нам возможность записывать и удалять JSP-файлы.

Нельзя просто так взять и загрузить шелл через PUT
Нельзя просто так взять и загрузить шелл через PUT
 

Базовые детали уязвимостей

Для обработки запросов к JSP и JSPX скрипты используют класс org.apache.jasper.servlet.JspServlet.

/conf/web.xml
246:     <servlet>
247:         <servlet-name>jsp</servlet-name>
248:         <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>

А за обработку остальных файлов отвечает org.apache.catalina.servlets.DefaultServlet. Именно в нем и реализован метод PUT.

/java/org/apache/catalina/servlets/DefaultServlet.java
539:     /**
540:      * Process a PUT request for the specified resource.
...
548:     @Override
549:     protected void doPut(HttpServletRequest req, HttpServletResponse resp)
550:         throws ServletException, IOException {
551:
552:         if (readOnly) {
553:             resp.sendError(HttpServletResponse.SC_FORBIDDEN);
554:             return;
555:         }

Как видишь, работа этого метода зависит от опции readOnly, которую мы и выключили, так как по умолчанию она установлена в true.

/java/org/apache/catalina/servlets/DefaultServlet.java
162:     protected boolean readOnly = true;

Идея эксплоита заключается в том, чтобы заставить PUT-запрос к файлу JSP обрабатываться с помощью DefaultServlet. Это можно провернуть несколькими способами. Чтобы лучше вникнуть в детали, сначала мы поговорим о методах, которые можно использовать только в версиях для Windows.

Давай запустим Tomcat версии 7.0.79 и выполним такой запрос:

PUT /read.txt%20 HTTP/1.1
Host: tomcat.visualhack:8080
Connection: close
Content-Length: 3

any
Запрос на создание файла с пробелом в конце имени
Запрос на создание файла с пробелом в конце имени

Если ты знаешь про особенности и ограничения в названиях файлов системы Windows, то, увидев пробел в конце пути, сразу же все поймешь. Дело в том, что файлы, создаваемые штатными методами ОС, не могут содержать пробелы в начале или в конце имени — те просто отбрасываются. Но ведь Tomcat написан на Java, скажешь ты. Чтобы все прояснить, посмотрим на ключевые шаги обработки нашего запроса.

Ты уже знаешь, что за его обработку отвечает DefaultServlet. Если файл еще не существует, то выполнение передается методу bind.

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

Вариант 1. Оформи подписку на «Хакер», чтобы читать все материалы на сайте

Подписка позволит тебе в течение указанного срока читать ВСЕ платные материалы сайта. Мы принимаем оплату банковскими картами, электронными деньгами и переводами со счетов мобильных операторов. Подробнее о подписке

Вариант 2. Купи один материал

Заинтересовала информация, но нет возможности оплатить подписку? Тогда этот вариант для тебя! Обрати внимание: этот способ покупки доступен только для материалов, опубликованных более двух месяцев назад.


1 комментарий

  1. vernikitina

    22.10.2017 at 10:38

    Так то круто, вот только какой нормальный админ будет включать put в tomcat?

Оставить мнение

Check Also

Обгоняя флагманы. Большой гайд по оптимизации Android

Тебе не хватает заряда аккумулятора? Надоели тормоза в приложениях? Не отчаивайся и не тор…