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

Баг в конце марта обнаружил латвийский исследователь Янис Крустс (Jānis Krusts) из IT Centrs. Ей присвоили номер CVE-2019-3398. Баг сводится к тому, что отсутствие фильтрации имен файлов в DownloadAllAttachmentsOnPageAction дает возможность атакующему выйти из временной директории и записать файл с произвольным содержимым в любую папку, доступную для записи.

Для проведения атаки требуется учетная запись с правами создания и редактирования записей. Уязвимы множество версий в разных ветках приложения. Все, что вышло аж с Confluence 2.0.0 вплоть до Confluence 6.6.12, уязвимо. Также проблемными оказались версии с 6.7.0 до 6.12.3, версии с 6.13.0 по 6.13.3, с 6.14.0 до 6.14.2 и с 6.15.0 по 6.15.2 включительно. Более детальный список можно посмотреть в официальной базе знаний.

 

Стенд

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

$ docker run --rm --name=confluence.vh --hostname=conflvh -p 8090:8090 -p 8091:8091 atlassian/confluence-server:6.9.0

Инсталлируем приложение.

Установка Atlassian Confluence 6.9.0
Установка Atlassian Confluence 6.9.0

Далее создаем администратора системы. Для тестирования уязвимости нам понадобится пользователь с возможностью загружать аттачи. Создаем его, и стенд готов.

Готовый стенд с Confluence 6.9.0
Готовый стенд с Confluence 6.9.0
 

Детали уязвимости CVE-2019-3398

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

Загруженные файлы к посту блога в Confluence
Загруженные файлы к посту блога в Confluence

Обрати внимание на кнопку Download All — она скачивает все файлы. Перед этим они любезно упаковываются в ZIP, который и отправляется пользователю. В моем случае ссылка имеет вид http://confluence.vh:8090/pages/downloadallattachments.action?pageId=65601. Из названия экшена видно, что за скачивание отвечает класс DownloadAllAttachmentsOnPageAction. Он расположен в файле confluence/WEB-INF/lib/confluence-6.9.0.jar. Для декомпиляции я воспользуюсь утилитой JD-GUI версии 1.5.

/com/atlassian/confluence/pages/actions/DownloadAllAttachmentsOnPageAction.java
01: package com.atlassian.confluence.pages.actions;
02:
...
18: public class DownloadAllAttachmentsOnPageAction extends AbstractPageAwareAction {
19:   AttachmentManager attachmentManager;

Чтобы сразу определить, где конкретно проблема, можно заглянуть в этот же файл, только в пропатченной версии, например 6.12.4.

/confluence-6.12.4/com/atlassian/confluence/pages/actions/DownloadAllAttachmentsOnPageAction.java
19: public class DownloadAllAttachmentsOnPageAction extends AbstractPageAwareAction {
20:   AttachmentManager attachmentManager;
...
32:   public String execute() throws Exception {
33:     List<Attachment> latestAttachments = this.attachmentManager.getLatestVersionsOfAttachments(getPage());
34:     for (Attachment attachment : latestAttachments) {
35:       File tmpFile = new File(getTempDirectoryForZipping(), ConfluenceFileUtils.extractFileName(attachment.getFileName()));
/confluence-6.9.0/com/atlassian/confluence/pages/actions/DownloadAllAttachmentsOnPageAction.java
18: public class DownloadAllAttachmentsOnPageAction extends AbstractPageAwareAction {
19:   AttachmentManager attachmentManager;
...
31:   public String execute() throws Exception {
32:     List<Attachment> latestAttachments = this.attachmentManager.getLatestVersionsOfAttachments(getPage());
33:     for (Attachment attachment : latestAttachments) {
34:       File tmpFile = new File(getTempDirectoryForZipping(), attachment.getFileName());

Как видишь, второй параметр, который отвечает за имя аттача, в новой версии метода execute фильтруется при помощи extractFileName.

/confluence-6.12.4/com/atlassian/confluence/util/io/ConfluenceFileUtils.java
82:   public static String extractFileName(String pathname) {
83:     if (pathname == null)
84:       return null;
85:     return (new File(pathname)).getName();
86:   }

Значит, проблема в имени. Посмотрим на содержимое класса DownloadAllAttachmentsOnPageAction, а именно метод execute.

/com/atlassian/confluence/pages/actions/DownloadAllAttachmentsOnPageAction.java
31:   public String execute() throws Exception {
32:     List<Attachment> latestAttachments = this.attachmentManager.getLatestVersionsOfAttachments(getPage());
33:     for (Attachment attachment : latestAttachments) {

Сначала данные всех файлов попадают в массив latestAttachments, затем функция for перебирает его элементы и читает содержимое каждого файла. Обрати внимание, что создается объект типа File. Он указывает на временный файл, имя которого эквивалентно имени аттача.

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

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

Подпишись на «Хакер» по выгодной цене!

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

Аватар

aLLy

Специалист по информационной безопасности в ONsec. Research, ethical hacking and Photoshop.

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

Check Also

Поймать нарушителя! Учимся детектировать инструменты атак на Windows

Атаки на Windows в наше время одна из наиболее реальных угроз для компаний. При этом исход…