В этой статье мы поговорим о баге в 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. Присоединись к сообществу «Xakep.ru», чтобы читать все материалы на сайте

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

Вариант 2. Открой один материал

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


  • Подпишись на наc в Telegram!

    Только важные новости и лучшие статьи

    Подписаться

  • Подписаться
    Уведомить о
    1 Комментарий
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии