Concourse Enumeration & Attacks
Last updated
Last updated
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Concourse має п'ять ролей:
Concourse Admin: Ця роль надається лише власникам основної команди (за замовчуванням початкова команда concourse). Адміністратори можуть конфігурувати інші команди (наприклад: fly set-team
, fly destroy-team
...). Дозволи цієї ролі не можуть бути змінені за допомогою RBAC.
owner: Власники команди можуть змінювати все в межах команди.
member: Члени команди можуть читати та писати в межах ресурсів команди, але не можуть змінювати налаштування команди.
pipeline-operator: Оператори конвеєра можуть виконувати операції конвеєра, такі як запуск збірок і закріплення ресурсів, однак вони не можуть оновлювати конфігурації конвеєра.
viewer: Глядачі команди мають доступ "тільки для читання" до команди та її конвеєрів.
Крім того, дозволи ролей owner, member, pipeline-operator та viewer можуть бути змінені шляхом налаштування RBAC (конфігуруючи, більш конкретно, його дії). Читайте більше про це за адресою: https://concourse-ci.org/user-roles.html
Зверніть увагу, що Concourse групує конвеєри всередині команд. Тому користувачі, які належать до команди, зможуть керувати цими конвеєрами, і може існувати кілька команд. Користувач може належати до кількох команд і мати різні дозволи в кожній з них.
У YAML конфігураціях ви можете налаштувати значення, використовуючи синтаксис ((_source-name_:_secret-path_._secret-field_))
.
З документації: source-name є необов'язковим, і якщо його пропустити, буде використано менеджер облікових даних на рівні кластера, або значення може бути надано статично.
Необов'язкове _secret-field_ вказує на поле у отриманому секреті для читання. Якщо його пропустити, менеджер облікових даних може вибрати для читання 'поле за замовчуванням' з отриманих облікових даних, якщо таке поле існує.
Крім того, secret-path та secret-field можуть бути оточені подвійними лапками "..."
, якщо вони містять спеціальні символи такі як .
та :
. Наприклад, ((source:"my.secret"."field:1"))
встановить secret-path на my.secret
і secret-field на field:1
.
Статичні змінні можуть бути вказані в кроках завдань:
Or using the following fly
аргументи:
-v
or --var
NAME=VALUE
встановлює рядок VALUE
як значення для змінної NAME
.
-y
or --yaml-var
NAME=VALUE
парсить VALUE
як YAML і встановлює його як значення для змінної NAME
.
-i
or --instance-var
NAME=VALUE
парсить VALUE
як YAML і встановлює його як значення для змінної екземпляра NAME
. Дивіться Групування конвеєрів, щоб дізнатися більше про змінні екземпляра.
-l
or --load-vars-from
FILE
завантажує FILE
, YAML документ, що містить відповідність імен змінних до значень, і встановлює їх усі.
Існують різні способи, як Менеджер облікових даних може бути вказаний в конвеєрі, читайте як в https://concourse-ci.org/creds.html. Більше того, Concourse підтримує різні менеджери облікових даних:
Зверніть увагу, що якщо у вас є якийсь доступ на запис до Concourse, ви можете створювати завдання для екстракції цих секретів, оскільки Concourse повинен мати можливість отримувати до них доступ.
Щоб перерахувати середовище concourse, спочатку потрібно зібрати дійсні облікові дані або знайти авторизований токен, ймовірно, в конфігураційному файлі .flyrc
.
Щоб увійти, вам потрібно знати кінцеву точку, ім'я команди (за замовчуванням main
) та команду, до якої належить користувач:
fly --target example login --team-name my-team --concourse-url https://ci.example.com [--insecure] [--client-cert=./path --client-key=./path]
Отримати налаштовані цілі:
fly targets
Перевірити, чи є налаштоване з'єднання з ціллю все ще дійсним:
fly -t <target> status
Отримати роль користувача щодо вказаної цілі:
fly -t <target> userinfo
Зверніть увагу, що API токен за замовчуванням зберігається в $HOME/.flyrc
, ви, обшукуючи машини, можете знайти там облікові дані.
Отримати список команд
fly -t <target> teams
Отримати ролі в команді
fly -t <target> get-team -n <team-name>
Отримати список користувачів
fly -t <target> active-users
Список конвеєрів:
fly -t <target> pipelines -a
Отримати yaml конвеєра (чутлива інформація може бути знайдена в визначенні):
fly -t <target> get-pipeline -p <pipeline-name>
Отримати всі змінні конфігурації конвеєра:
for pipename in $(fly -t <target> pipelines | grep -Ev "^id" | awk '{print $2}'); do echo $pipename; fly -t <target> get-pipeline -p $pipename -j | grep -Eo '"vars":[^}]+'; done
Отримати всі імена секретів конвеєра, що використовуються (якщо ви можете створити/змінити завдання або захопити контейнер, ви можете їх екстрактувати):
Список робітників:
fly -t <target> workers
Список контейнерів:
fly -t <target> containers
Список збірок (щоб побачити, що виконується):
fly -t <target> builds
admin:admin
test:test
У попередньому розділі ми бачили, як ви можете отримати всі назви та змінні секретів, які використовуються в конвеєрі. Змінні можуть містити чутливу інформацію, а назва секретів буде корисною пізніше для спроби їх вкрасти.
Якщо у вас достатньо привілеїв (роль учасника або більше), ви зможете перелічити конвеєри та ролі і просто отримати сесію всередині контейнера <pipeline>/<job>
за допомогою:
З цими правами ви можете:
Вкрасти секрети всередині контейнера
Спробувати втекти на вузол
Перерахувати/Зловживати метаданими хмари (з пода та з вузла, якщо це можливо)
Якщо у вас достатньо привілеїв (роль учасника або більше), ви зможете створювати/модифікувати нові конвеєри. Перевірте цей приклад:
З модифікацією/створенням нового конвеєра ви зможете:
Вкрасти секрети (через їх виведення або зайшовши в контейнер і запустивши env
)
Вийти на вузол (надавши вам достатньо привілеїв - privileged: true
)
Перерахувати/Зловживати метаданими хмари (з пода та з вузла)
Видалити створений конвеєр
Це схоже на попередній метод, але замість модифікації/створення цілого нового конвеєра ви можете просто виконати користувацьке завдання (що, ймовірно, буде набагато прихованішим):
У попередніх розділах ми бачили, як виконати привілейоване завдання з concourse. Це не надасть контейнеру точно такого ж доступу, як привілейований прапор у контейнері docker. Наприклад, ви не побачите пристрій файлової системи вузла в /dev, тому втеча може бути більш "складною".
У наступному PoC ми будемо використовувати release_agent для втечі з деякими невеликими змінами:
Як ви, можливо, помітили, це просто регулярний escape release_agent, просто модифікуючи шлях cmd у вузлі
Регулярний escape release_agent з незначною модифікацією достатній для цього:
Навіть якщо веб-контейнер має деякі засоби захисту вимкненими, він не працює як звичайний привілейований контейнер (наприклад, ви не можете монтувати і можливості дуже обмежені, тому всі прості способи втечі з контейнера марні).
Однак він зберігає локальні облікові дані у відкритому тексті:
Ви можете використовувати ці облікові дані для входу на веб-сервер та створення привілейованого контейнера та втечі до вузла.
У середовищі ви також можете знайти інформацію для доступу до екземпляра postgresql, який використовує concourse (адреса, ім'я користувача, пароль та база даних серед іншої інформації):
Це лише кілька цікавих нотаток про службу, але оскільки вона слухає лише на localhost, ці нотатки не матимуть жодного впливу, який ми ще не експлуатували раніше
За замовчуванням кожен працівник concourse буде запускати службу Garden на порту 7777. Ця служба використовується веб-майстром для вказівки працівнику що потрібно виконати (завантажити зображення та виконати кожне завдання). Це звучить досить добре для зловмисника, але є кілька хороших захистів:
Вона виключно локальна (127..0.0.1), і я думаю, що коли працівник аутентифікується проти вебу за допомогою спеціальної служби SSH, створюється тунель, щоб веб-сервер міг спілкуватися з кожною службою Garden всередині кожного працівника.
Веб-сервер моніторить запущені контейнери кожні кілька секунд, і неочікувані контейнери видаляються. Тож якщо ви хочете запустити власний контейнер, вам потрібно втрутитися в зв'язок між веб-сервером і службою garden.
Працівники concourse працюють з високими привілеями контейнера:
Однак, такі техніки, як mounting пристрою /dev вузла або release_agent не спрацюють (оскільки реальний пристрій з файловою системою вузла недоступний, лише віртуальний). Ми не можемо отримати доступ до процесів вузла, тому втеча з вузла без експлойтів ядра ускладнюється.
У попередньому розділі ми бачили, як втекти з привілейованого контейнера, тому якщо ми можемо виконувати команди в привілейованому контейнері, створеному поточним робітником, ми могли б втекти до вузла.
Зверніть увагу, що граючи з concourse, я помітив, що коли новий контейнер створюється для виконання чогось, процеси контейнера доступні з контейнера робітника, тому це як контейнер, що створює новий контейнер всередині нього.
Отримання доступу до запущеного привілейованого контейнера
Створення нового привілейованого контейнера
Ви можете дуже легко створити новий контейнер (просто запустіть випадковий UID) і виконати щось на ньому:
Однак веб-сервер перевіряє кожні кілька секунд контейнери, які працюють, і якщо буде виявлено несподіваний, він буде видалений. Оскільки зв'язок відбувається по HTTP, ви можете підробити зв'язок, щоб уникнути видалення несподіваних контейнерів:
https://concourse-ci.org/vars.html
Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)