Взлом Jenkins, часть 1 — игра с динамической маршрутизацией| onadmin.ru

Автор: | Июль 15, 2019

В области разработки программного обеспечения непрерывная интеграция и непрерывная доставка — это лучшая практика для разработчиков по сокращению рутинных работ. В CI / CD наиболее известным инструментом является Jenkins. Из-за простоты использования, потрясающей системы Pipeline и интеграции Container, Jenkins также является наиболее широко используемым приложением CI / CD в мире. Согласно отчету об экосистеме JVM, подготовленному Snyk в 2018 году, Jenkins занимал около 60% рынка по исследованию серверов CI / CD.

Для Red Teamers Дженкинс также является полем битвы, которое каждый хакер хотел бы контролировать. Если кто-то получит контроль над сервером Jenkins, он может получить количество исходного кода и учетных данных или даже контролировать узел Jenkins! В наших случаях с DEVCORE Red Team есть также несколько случаев, когда вся корпорация взломана просто с сервера Jenkins в качестве нашей точки входа!

Эта статья в основном о кратком обзоре безопасности Jenkins за последний год. В ходе этого обзора мы обнаружили 5 уязвимостей, в том числе:

  • CVE-2018-1999002 — Ошибка чтения произвольного файла
  • CVE-2018-1000600 — CSRF и пропущенные проверки прав доступа в GitHub Plugin
  • CVE-2018-1999046 — Неавторизованные пользователи могут получить доступ к журналам агентов
  • CVE-2018-1000861 — Выполнение кода через созданные URL-адреса
  • CVE-2019-1003000 — Обход песочницы в плагинах безопасности скриптов и конвейера
  • CVE-2019-1003001 — Обход песочницы в плагинах безопасности скриптов и конвейера
  • CVE-2019-1003002 — Обход песочницы в плагинах безопасности скриптов и конвейера

Среди них наиболее обсуждаемой является уязвимость CVE-2018-1999002. Это произвольная уязвимость чтения файлов через необычный вектор атаки! Лаборатория безопасности Tencent YunDing написала подробное руководство по этому вопросу, а также продемонстрировала, как использовать эту уязвимость при произвольном чтении файлов в RCE на реальном сайте Jenkins, найденном в Shodan!

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

ANONYMOUS_READ=True of CVE-2018-1999002!

Если вы просто посмотрите на консультативное описание, вам может быть любопытно — Реально ли добиться выполнения кода с помощью просто созданного URL?

С моей точки зрения, эта уязвимость является просто обходом списка контроля доступа (ACL), но, поскольку это проблема архитектуры, а не отдельной программы, существуют различные способы использования этой ошибки! Чтобы погасить долг по дизайну, команда Jenkins также предпринимает много усилий (исправления на стороне Jenkins и на стороне степлера), чтобы исправить это. Патч не только вводит новый черный и белый списки маршрутизации, но также расширяет оригинальный интерфейс поставщика услуг (SPI) для защиты маршрутизации Jenkins. Теперь давайте выясним, почему Дженкинс должен сделать такую огромную модификацию кода!

 

Область обзора


Это не полный анализ кода (общий анализ безопасности занимает много времени…), поэтому этот обзор просто нацелен на серьезные ошибки. Объем обзора включает в себя:

Jenkins Core
Степлер Web Framework
Предлагаемые плагины

Во время установки Jenkins спрашивает, хотите ли вы установить предлагаемые плагины, такие как Git, GitHub, SVN и Pipeline. В основном, большинство людей выбирают «да», или они получат неудобный и сложный в использовании Дженкинс.

Hacking Jenkins Part 1 - Play with Dynamic Routing (EN) | DEVCORE

Hacking Jenkins Part 1 - Play with Dynamic Routing (EN) | DEVCORE

Уровни привилегий

Поскольку уязвимость является обходом ACL, нам нужно сначала ввести уровень привилегий в Jenkins! В Jenkins существуют различные виды ролей ACL, в Jenkins даже есть специальный плагин Matrix Authorization Strategy Plugin (также в списке предлагаемых плагинов) для настройки подробного разрешения для каждого проекта. С точки зрения злоумышленника, мы грубо классифицируем ACL на 3 типа:

1. Полный доступ

Вы можете полностью контролировать Дженкинс. Как только злоумышленник получит это разрешение, он может выполнить произвольный код Groovy через консоль Script!

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

2. Режим только для чтения

Это можно включить в Configure Global Security и установить флажок:

Разрешить анонимный доступ для чтения

В этом режиме все содержимое является видимым и читаемым. Такие как журналы агента и информация о задании / узле. Для злоумышленников лучшим преимуществом этого режима является доступность множества частных исходных кодов! Однако злоумышленник не может ничего делать дальше или выполнять скрипты Groovy!

Хотя это не настройка по умолчанию, для DevOps они все равно могут открыть эту опцию для автоматизации. Согласно небольшому опросу на Shodan, около 12% серверов включили этот режим! Мы назовем этот режим

ANONYMOUS_READ=True в следующих разделах.

3. Режим аутентификации

Это режим «по умолчанию». Без действительных учетных данных вы не увидите никакой информации! Мы будем использовать ANONYMOUS_READ = False для вызова этого режима в следующих разделах.

Анализ уязвимостей

Чтобы объяснить эту уязвимость, мы начнем с динамической маршрутизации Jenkins. Чтобы предоставить разработчикам больше гибких возможностей, Jenkins использует соглашение об именах для разрешения URL-адреса и динамического вызова метода. Сначала Дженкинс токенизирует все URL-адреса с помощью /, и начинается с jenkins.model.Jenkins как точки входа, которая соответствует токену один за другим. Если токен соответствует (1) члену открытого класса или (2) методу открытого класса, соответствуют следующим соглашениям об именах, Jenkins вызывает рекурсивно!

  1. get()
  2. get(String)
  3. get(Int)
  4. get(Long)
  5. get(StaplerRequest)
  6. getDynamic(String, …)
  7. doDynamic(…)
  8. do(…)
  9. js(…)
  10. Class method with @WebMethod annotation
  11. Class method with @JavaScriptMethod annotation

Похоже, что Jenkins предоставляет разработчикам большую гибкость. Однако слишком большая свобода не всегда хорошая вещь. Есть две проблемы, основанные на этом соглашении об именах!

1. Все это подкласс java.lang.Object

В Java все является подклассом java.lang.Object. Поэтому все объекты должны существовать методомgetClass(), и именем getClass()просто соответствует правилу именования #1! Поэтому метод getClass() также может быть вызван во время динамической маршрутизации Jenkins!

2. Обход белого списка

Как упоминалось ранее, самая большая разница между ANONYMOUS_READ=True и ANONYMOUS_READ=False в том, что если флаг установлен как False, точка входа сделает еще одну регистрацию jenkins.model.Jenkins#getTarget(). Проверка является проверкой префикса URL на основе белого списка, и вот список:

 

Это означает, что вы ограничены этими входами, но если вы можете найти перекрестную ссылку из перехода из белого списка на другие объекты, вы все равно можете обойти эту проверку префикса URL! Кажется, это немного сложно понять. Давайте приведем простой пример, демонстрирующий динамическую маршрутизацию:

Приведенный выше URL будет вызывать следующие методы в последовательности!

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

Как только мы реализуем принцип, оставшаяся часть похожа на решение лабиринта. jenkins.model.Jenkins является точкой входа. Каждый член этого объекта может ссылаться на новый объект, поэтому наша работа состоит в том, чтобы связать объект слой за слоем до выходной двери, то есть вызова опасного метода!

Кстати, самое печальное, что эта уязвимость не может вызвать SETTER, иначе это определенно будет еще одна интересная ошибка манипуляции с classLoader, такая как Struts2 RCE и Spring Framework RCE !!

Как использовать?


Как эксплуатировать? Короче говоря, все, чего может достичь эта ошибка, — это использовать объекты перекрестных ссылок для обхода политики ACL. Чтобы использовать его, нам нужно найти подходящий гаджет, чтобы было удобнее вызывать объект, который мы предпочитаем, в этом объектном лесу! Здесь мы выбираем гаджет:

Гаджет будет последовательно вызывать следующие методы.

В Jenkins все настраиваемые объекты будут расширять тип hudson.model.Descriptor. И любой класс, который расширяет тип дескриптора, доступен методом hudson.model.DescriptorByNameOwner # getDescriptorByName (String). Всего доступно около 500 типов классов! Но из-за архитектуры Дженкинс. Большинство разработчиков проверят разрешение перед опасным действием снова. Так что даже мы можем найти объектную ссылку на консоль сценариев без разрешения Jenkins.RUN_SCRIPTS, мы до сих пор ничего не можем сделать 🙁

Несмотря на это, эту уязвимость все еще можно рассматривать как трамплин, чтобы обойти первое ограничение ACL и связать другие ошибки. В нашем примере мы покажем 3 цепочки уязвимостей! (Хотя мы только показываем 3 случая, их больше 3! Если вас интересует, настоятельно рекомендуется найти другие самостоятельно. 😛 )

P.S. Следует отметить, что в методе getUser([username]), это вызовет getOrCreateById(...)с create флагом, установленным в True. Это приводит к созданию временного пользователя в памяти (который будет указан в списке пользователей, но не сможет войти). Несмотря на то, что это безвредно, оно все еще признается как проблема безопасности в SECURITY-1128.

1. Предварительная аутентификация информации о пользователе

Во время тестирования Jenkins, это обычный сценарий, когда вы хотите выполнить атаку методом перебора, но вы не знаете, какую учетную запись вы можете использовать (действительные учетные данные могут прочитать источник, по крайней мере, поэтому стоит быть первой попыткой).

В этой ситуации эта уязвимость полезна!

Из-за отсутствия разрешения на проверку функциональности поиска. Изменяя ключевое слово от a до z, злоумышленник может перечислить всех пользователей в Jenkins!

PoC:

Hacking Jenkins Part 1 - Play with Dynamic Routing (EN) | DEVCORE

Кроме того, эта уязвимость может быть также связана с SECURITY-514, о котором сообщаетAnanthapadmanabhan S R утечка адреса электронной почты пользователя! Такие как:

2. Связь с CVE-2018-1000600 к SSRF с предварительной авторизацией

Следующая ошибка — CVE-2018-1000600, об этом сообщает Orange Tsai (да, это я: P). Об этой уязвимости официальное описание:

Уязвимость CSRF и отсутствующие проверки прав доступа в плагине GitHub позволили захватывать учетные данные

Он может извлечь любые сохраненные учетные данные с известным идентификатором учетных данных в Jenkins. Но идентификатор учетных данных является случайным UUID, если не предоставлено пользовательское значение. Таким образом, кажется, невозможно использовать это? (Или, если кто-то знает, как получить идентификационные данные, пожалуйста, скажите мне!)

PoC:

Hacking Jenkins Part 1 - Play with Dynamic Routing (EN) | DEVCORE

 

3. Предварительная авторизация удаленного выполнения кода

PLEASE DON’T BULLSHIT, WHERE IS THE RCE!!!

Чтобы максимизировать воздействие, я также нахожу, что ИНТЕРЕСНОЕ удаленное выполнение кода может быть приковано этой уязвимостью к заслуженному RCE! Но это все еще на ответственном процессе раскрытия. Пожалуйста, подождите и посмотрите часть 2! (Будет опубликовано 19 февраля: P)

СДЕЛАТЬ

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

  • Получить ссылку на объект плагина в ANONYMOUS_READ = False. Если это можно сделать, он может обойти ограничение ACL CVE-2018-1999002 и CVE-2018-6356 для действительно предаварийного чтения произвольного файла!
  • Найдите другой гаджет для вызова метода getDescriptorByName (String) в ANONYMOUS_READ = False. Чтобы исправить SECURITY-672, Jenkins применяет проверку hudson.model.User, чтобы обеспечить наименьшие привилегии Jenkins.READ. Таким образом, оригинальный гаджет выйдет из строя после версии Jenkins 2.138.

 

Подтверждение

Спасибо команде безопасности Jenkins, особенно Дэниелу Беку, за координацию и исправление ошибок! Вот краткий график:

  • May 30, 2018 — Report vulnerabilities to Jenkins
  • Jun 15, 2018 — Jenkins patched the bug and assigned CVE-2018-1000600
  • Jul 18, 2018 — Jenkins patched the bug and assigned CVE-2018-1999002
  • Aug 15, 2018 — Jenkins patched the bug and assigned CVE-2018-1999046
  • Dec 05, 2018 — Jenkins patched the bug and assigned CVE-2018-1000861
  • Dec 20, 2018 — Report Groovy vulnerability to Jenkins
  • Jan 08, 2019 — Jenkins patched Groovy vulnerability and assigned CVE-2019-1003000, CVE-2019-1003001 and CVE-2019-1003002

Источник: https://devco.re/blog/2019/01/16/hacking-Jenkins-part1-play-with-dynamic-routing-en/

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *