1 puan yazan GN⁺ 2025-04-01 | 1 yorum | WhatsApp'ta paylaş
  • Kısa süreli geçerli olan açık bir GITHUB_TOKEN, CodeQL kullanan birçok deponun GitHub Actions workflow’larında kod çalıştırmaya uzanan bir tedarik zinciri saldırısı yolunu mümkün kılabilirdi
  • Token, github/codeql-action deposundaki başarısız bir debug workflow’un yüklediği workflow artifact içinde yer alıyordu ve contents: write, actions: write, packages: write izinlerine sahip bir GitHub App kurulum token’ıydı
  • Saldırının başarıya ulaşması, artifact yüklendikten iş tamamlanana kadar geçen sürede token’ın indirilip kullanılmasına bağlı olan bir race condition durumuna dayanıyordu; gerçek loglara göre yaklaşık 1.022 saniye, gözleme göre yaklaşık 2 saniye içinde branch oluşturma, poc.txt push etme ve tag oluşturma başarıyla yapıldı
  • Varsayılan CodeQL yapılandırması dahili olarak github/codeql-action deposunun v3 tag’ini çalıştırıyordu ve bu tag değiştirilemez değildi; bu nedenle saldırgan tag’i kötü amaçlı bir commit’e taşısa, varsayılan CodeQL workflow’unu kullanan depolar da etkilenebilirdi
  • GitHub, bildirimden yaklaşık 3 saat sonra debug artifact yüklemelerini devre dışı bırakan bir PR açtı, CVE-2025-24362 atadı ve advisory’de platform ya da sistem ihlaline dair kanıt bulunmadığını belirtti

Açık artifact ile başlayan CodeQL tedarik zinciri saldırı yolu

  • Açığa çıkan tek bir secret, GitHub CodeQL’e yönelik potansiyel bir tedarik zinciri saldırısına dönüşebilirdi
  • Bu secret bir seferde yalnızca yaklaşık 1.022 saniye geçerliydi, ancak bu süre içinde saldırganın GitHub Actions workflow içinde kod çalıştırmaya giden adımları yerine getirmesi mümkündü
  • Etki alanı hem GitHub Cloud hem de GitHub Enterprise’a uzanabilirdi
  • Olası zararlar şunlardı
    • CodeQL kullanan private depoların kaynak kodunun sızdırılması
    • CodeQL workflow job’ları içindeki GitHub Actions secrets bilgilerinin ele geçirilmesi
    • CodeQL workflow’larının çalıştığı iç altyapıda kod çalıştırılması
    • CodeQL kullanan depolarda GitHub Actions Cache kullanan workflow’ların secrets bilgilerinin ele geçirilmesi
  • GitHub advisory’sine göre GitHub, platform veya sistem ihlaline dair bir kanıt bulmadı

Secret’ın nasıl bulunduğu

  • GitHub Actions workflow artifact’lerini indirip arşivleri özyineli olarak açtıktan sonra Nosey Parker ile secret taraması yapan bir Actions Artifacts Secret Scanner kullanıldı
  • Bu özellik Chariot’a entegre edildi ve Gato özelliği olarak açık kaynak hâline getirildi
  • Bir gün boyunca yapılan taramanın ardından github/codeql-action deposunun artifact’lerinde token bulundu
    • Hedef artifact, “PR Check – Debug artifacts after failure” workflow’unun yüklediği my-debug-artifacts zip dosyasıydı
    • İçindeki my-db-java-partial.zip açıldığında, crash report içinde ghs_ ile başlayan bir GitHub Token tespit edildi
    • Manuel inceleme sonucunda bunun, GitHub Runner ortam değişkenlerini içeren bir dosyada saklanan GitHub App kurulum token’ı olduğu anlaşıldı

GitHub Actions, artifact ve CodeQL arasındaki bağlantı yapısı

  • GitHub Actions, YAML workflow’larında tanımlanan işleri runner üzerinde çalıştıran bir CI/CD platformudur
  • Her workflow çalıştırması, otomatik olarak oluşturulan bir GitHub App kurulum token’ı olan GITHUB_TOKEN üretir
    • Runner, workflow’un gerektirdiği işleri yapmak için bu token ile GitHub’a kimlik doğrular
    • İzinler workflow dosyası, depo ve organizasyon düzeyinde ayarlanabilir
  • GitHub Actions workflow artifact’i, workflow’un daha sonra kullanmak üzere GitHub Actions’a kaydettiği dosyalardır
    • Varsayılan olarak depoda okuma yetkisi olan herkes erişebilir
    • En fazla 90 gün boyunca saklanır
  • CodeQL, GitHub’un kod analiz motorudur ve GitHub depolarında statik analiz yaparak zafiyetleri bulmak için kullanılır
  • CodeQL gibi güvenlik araçları hassas sistemlere ve verilere erişmek zorunda kalabildiğinden, ele geçirilirlerse bir arka kapı hâline gelebilirler

Token izinleri ve race condition

  • Workflow loglarındaki “Setup Job” adımı, ilgili GITHUB_TOKEN’ın tam yazma iznine sahip olduğunu gösterdi
  • Özellikle kritik izinler şunlardı
    • contents: write: branch oluşturma, tag oluşturma, release artifact yükleme
    • actions: write: Actions işleri ve workflow_dispatch event’ini tetikleme
    • packages: write: package yükleme
  • Token yalnızca ilgili workflow job’ı çalıştığı sürece geçerli olduğundan, saldırı için üç koşul gerekliydi
    • Token’ın yazma iznine sahip olması
    • Job tamamlanmadan önce artifact alınmasına izin veren upload artifact API v4’ün kullanılması
    • Artifact yükleme ile job tamamlanması arasındaki sürenin token’ı indirme, arşivi açma ve kullanma için yeterli olması
  • CodeQL, actions/upload-artifact action’ını doğrudan kullanmıyor; bunun yerine kaynak kod içinden upload artifact istemcisini manuel olarak kullanıyordu ve kod yorumlarına göre version 4 kullanılıyordu
  • Ham GitHub loglarına göre zaman aralığı çok kısaydı
    • “Finalizing artifact upload”: 17:22:09.888
    • “Cleaning up orphan processes”: 17:22:10.911
    • Hesaplamaya göre yaklaşık 1.022 saniyeydi; gözleme göre cleanup sonrasında token yaklaşık 1 saniye daha geçerli kaldığından toplam yaklaşık 2 saniye kabul edildi

PoC: artifact_racer.py çalıştırılması

  • Doğrulama için artifact_racer.py adlı bir Python script’i yazıldı
  • Çalışma akışı şöyleydi
    • github/codeql-action deposunda “PR Check – Debug artifacts after failure” workflow’unun başlayıp başlamadığı sürekli sorgulanıyor
    • Çalışmakta olan workflow’un artifact’leri izleniyor
    • Artifact görünür görünmez indiriliyor ve GITHUB_TOKEN çıkarılıyor
    • Çıkarılan token ile yeni bir branch oluşturuluyor
    • Bu branch’e poc.txt adlı boş bir dosya push ediliyor
    • İlgili commit için yeni bir tag oluşturuluyor
  • Artifact boyutu yaklaşık 21MB olduğundan, süre içinde başarılı olmanın mümkün olduğu düşünüldü
  • Test deposunda başarı sağlandıktan sonra işlem github/codeql-action deposuna karşı çalıştırıldı
  • Yaklaşık 2 saat sonra workflow çalıştı ve script token’ı alarak branch oluşturma, dosya push etme ve tag oluşturma işlemlerini başarıyla tamamladı

Tag manipülasyonunun etki alanını büyütmesi

  • Saldırgan, bu token ile korunmayan bir branch’e kötü amaçlı kod ekleyebilirdi
  • Daha gizli bir yöntem olarak, merge öncesi bir feature branch’e küçük kötü amaçlı değişiklikler koyup merge’ü beklemek de mümkündü
  • Tag oluşturma izni de kritikti
    • Kötü amaçlı kod içeren commit’e v3 tag’i eklenirse, codeql-action@v3ü manuel kullanan kullanıcılar kötü amaçlı kodu çalıştırabilirdi
  • Daha büyük etki, varsayılan CodeQL yapılandırmasından kaynaklanıyordu
    • Depo ayarlarından CodeQL varsayılan yapılandırmayla etkinleştirildiğinde, depo workflow listesinde görünmeyen özel bir GitHub Actions workflow’u çalışır
    • Bu workflow depo checkout, CodeQL başlatma, CodeQL taraması ve sonuç yükleme işlemlerini yapar
    • Dahili olarak github/codeql-action deposundaki action’ı, v3 tag’inin işaret ettiği commit üzerinden çalıştırır
  • O sırada v3 tag’i değiştirilemez değildi ve GitHub’un önerdiği workflow pinning de kullanılmıyordu
  • Saldırgan, ele geçirilmiş GITHUB_TOKEN ile v3 tag’ini kötü amaçlı bir commit’e taşıyabilirse, varsayılan CodeQL workflow’unu kullanan depolar kötü amaçlı CodeQL action’ını çalıştırabilirdi
  • CodeQL action’ı çalıştığı depodaki kaynak kodu checkout ettiği için, kötü amaçlı action varsayılan CodeQL yapılandırmasını kullanan depoların kaynak kodunu dışarı sızdırabilirdi

GitHub Actions Cache poisoning yolu

  • Varsayılan CodeQL action’ının GITHUB_TOKEN’ı yalnızca okuma iznine sahip olduğundan, sadece varsayılan yapılandırma ile doğrudan depo yazma işlemleri, release arka kapısı ya da workflow_dispatch üzerinden secrets ele geçirme mümkün değildi
  • Bunun yerine varsayılan CodeQL action’ı deponun main branch’inde çalışır
  • GitHub depolarında main branch, depo genelinde kullanılabilecek cache entry’leri yazabildiği için GitHub Actions cache poisoning fırsatı doğar
  • GitHub Actions Cache Poisoning, Adnan Khan’ın yazısında ele alınan bir tekniktir; Cacheract ise cache poisoning ile build pipeline içinde kalıcılık bırakan bir malware’dir
  • Saldırgan CodeQL workflow içinde Cacheract’i dağıtırsa şu akış mümkün olabilirdi
    • Cache entry’yi tahmin etme
    • İlgili entry’yi kötü amaçlı action ile ezme
    • actions/cache kullanan workflow’da kod çalıştırma elde etme
    • Bu workflow’un GitHub Actions secrets bilgilerini ve daha yüksek yetkili GITHUB_TOKEN’ını ele geçirme
  • Kötü amaçlı CodeQL action’ı tespit edilip zafiyet giderilse bile, Cacheract cache poisoning yapmaya devam edebilirdi
  • Hem CodeQL hem de actions/cache kullanan önemli repo örnekleri arasında Homebrew, Angular, Grafana yer alıyor

CVE-2025-24362 ve düzeltme

  • Bu açıklama sonucunda CVE-2025-24362 atandı
  • Açığa çıkan GITHUB_TOKEN, başarısız bir code scanning workflow’undan sonra CodeQL Action’ın yüklediği debug artifact içinde yer alıyordu
  • CodeQL Actions deposu kasıtlı olarak hataya düşürülüyordu, ancak diğer CodeQL Actions kullanıcılarında da benzer bir hata oluştuysa kendi secret’larını workflow ortam değişkenleri yoluyla açığa çıkarmış olabilirlerdi
  • Bu sorun CodeQL Action 3.28.3 sürümünde giderildi
  • En büyük potansiyel etki, CVE’nin kendisinden çok, CodeQL Actions deposunun istismar edilip CodeQL kullanıcılarına karşı bir tedarik zinciri saldırısı yürütülebilmesi yolunda yatıyordu

GitHub’un yanıtı ve önerilen önlemler

  • GitHub’un müdahale takvimi şöyleydi
    • 22 Ocak 2025 15:13 UTC: GitHub’a bildirim gönderildi
    • 22 Ocak 2025 17:48 UTC: GitHub alındıyı doğruladı
    • 22 Ocak 2025 18:28 UTC: GitHub zafiyeti doğruladı, “PR Check – Debug artifacts after failure” workflow’unu geçici olarak devre dışı bıraktı ve debug artifact yüklemelerini devre dışı bırakan bir PR gönderdi
    • 24 Ocak 2025: GitHub, CVE-2025-24362 atadı ve security advisory yayımladı
  • GitHub Actions workflow artifact’lerinde secret açığa çıkma riskini azaltmak için şu önlemler öneriliyor
    • Workflow artifact olarak yalnızca belirli dosya veya dizinleri yüklemek
    • Ortam değişkenlerini, .git/config dosyasını ve runner’ın <path_to_runner_dir>/_work/_temp/ dizinindeki dosyaları içeren artifact yüklemelerinden kaçınmak
    • GITHUB_TOKEN izinlerini salt okunur olacak şekilde sınırlamak
    • Artifact yüklemeden önce secret taraması yapmak

1 yorum

 
GN⁺ 2025-04-01
Hacker News yorumları
  • GitHub immutable actions özelliğini daha hızlı zorlasaydı bunun etkisi çok daha sınırlı olurdu.
    Bu özelliğin şu anda GitHub Actions saldırı yüzeyinin %70’inden fazlasını engelleyeceğini tekrar tekrar söylemek zorunda kalıyorum. Her hafta bir olay yaşandığını görünce artık yayımlanma zamanı geldi diye düşünüyorum.
    [1] https://github.com/features/preview/immutable-actions

    • Hâlâ önizleme aşamasındaysa muhtemelen bunun iyi bir nedeni vardır. Ciddi hatalar, güvenlik açıkları, acele edilirse daha büyük zarara yol açabilecek uyumluluk kırılmaları vb. olabilir.
  • Bu geçici tokenın neden yeni dağıtım oluşturma ve artifact attestations üretme yetkisine kadar sahip olduğuna dair bir açıklama yok.
    Düzeltme olarak debug loglarının kapatıldığını söylediler ama geçici token izinlerinin kod analiz motoruna daha uygun şekilde değiştirilip değiştirilmediğine yanıt vermediler.

    • Herkesin bildiği eski hikâye gibi. Geliştiren mühendis izin reddiyle karşılaşınca tüm izinleri vermiş, sonra da en az ayrıcalık seviyesine indirmek için geri dönmemiş.
    • GitHub Actions geçici token’ında workflow’da tanımlanmış izin kapsamı yoksa, depo ayarlarına bağlı olarak izin verici varsayılan kapsam ya da kısıtlayıcı varsayılan kapsam uygulanır. Bu ayar, organizasyon düzeyinde de tüm depoları kısıtlayacak şekilde yapılandırılabilir.
      Geçmişte varsayılan yalnızca izin verici ayardı; bu yüzden eski organizasyon ve depolarda ne yazık ki bu ayar sıkça kullanılıyor.
      Yeni bir depo oluşturduğunuzda üst organizasyonun varsayılanını devralır; biri değiştirmezse bu güvensiz varsayılan kalmaya devam eder. Kullanıcı geneli için bir ayar yok, bu yüzden kişisel sahipli yeni depolar kısıtlayıcı varsayılanı kullanır. Yeni oluşturulan organizasyonların da daha iyi varsayılanı kullandığını biliyorum.
      [0]: https://docs.github.com/en/actions/security-for-github-actio...
    • Geçici action token’ları varsayılan olarak tam yazma iznine sahiptir. Salt okunur sürümü kullanmak için bunu açıkça seçmeniz gerekir.

      Read and write permissions
      Workflows have read and write permissions in the repository for all scopes.
      Belgelerdeki şu satırı (https://docs.github.com/en/actions/security-for-github-actio...) tek başına okuyunca farklı düşünebilirsiniz.
      If the default permissions for the GITHUB_TOKEN are restrictive, you may have to elevate the permissions to allow some actions and commands to run successfully.
      Ama bizim GitHub organizasyonumuzda varsayılan "Read and write permissions" idi; bu yüzden o belge cümlesinin mantıklı olmadığını doğrulayabiliyorum.

    • 2023’teki Microsoft hack’i de buna benziyordu. CISA’nın güvenliğinin berbat olduğunu açıkça azarladığı bir olaydı; Microsoft’un olayı açıklamak için yayımladığı blog yazısında da yanıtlanmamış çok fazla soru vardı.
    • Debug loglarını kapatmanın hızlı bir geçici önlem olmasını umarım. Nihai düzeltme bu olmamalı.
  • CI ve CD’nin tamamen ayrı ortamlar olması gerektiğine giderek daha çok ikna oluyorum. CI ele geçirildi diye CD ile ilgili token’ların sızmaması gerekir.

    • Bu alan kişisel olarak çok ilgimi çekiyor; bence çözüm CD’yi ayrı, küçük ve özel amaçlı bir sisteme ayırmaktan ziyade CD’yi çok faktörlü hale getirmek.
      Örneğin "sub":"repo:octo-org/octo-repo:environment:prod"[1] gibi bir koşulun mutlaka sağlanmasını zorunlu kılabilir, sistemi daha sağlam yapmak isterseniz başka [fun claims][] de ekleyebilirsiniz.
      1: https://docs.github.com/en/actions/security-for-github-actio...
      fun claims: https://github.com/github/actions-oidc-debugger#readme
    • Özünde görevlerin ve ilgi alanlarının ayrımı böyle görünür. İyi proje örneklerinin de bazen bu şekilde çalıştığı oluyor. Somut teknikler, araçlar ve CI ile CD arasındaki sınır, nihai çıktının niteliğine göre değişir; ama kavramsal olarak tamamen doğru.
  • Müdahale süresi şaka değildi. GitHub’ın tepkisi epey etkileyici.

    • Tam yazma izni olan herkese açık bir token’ın açığa çıkması pek etkileyici değil.
  • Soyadı Prater olan biri olarak, bu adın Praetorian’dan gelmesi nedeniyle praetorian.com’a sahip olmayı gerçekten isterdim.

    • Bunun için 1995 yapımı “The Net” filmi çıkmadan önce bunu düşünmüş olman gerekirdi.
    • Onların gokart projesi harikaydı.
  • Herkese açık GitHub Actions kullanmak sorun davet etmektir; workflow süreçlerini analiz etmiyorsanız daha da öyle.
    Bunun yerine woodpecker veya diğer iyi CI builder’ları (circle, travis, gitlab vb.) kendiniz host etmeniz daha iyi.

  • OpenZFS PR’lerine CodeQL uygulamıştık. Bu OpenZFS için sorun değil. Çünkü kodumuz gizli değil :)

    • Kod gizli olmasa bile bunun iyi bir karar olduğunu sanmıyorum. Çünkü saldırgan koda veya release artifactlerine istediğini ekleyebilirdi.
      Yine de en azından hızlıca çözülmüş olması iyi.
  • Bu düzeltildi mi?

    • Yazıda ve buradaki yorumlarda belirtildiği gibi, evet. Ocak ayında bildirildikten sonra GitHub 3 saat içinde azaltıcı önlem aldı.
  • Bu sitenin performansı o kadar kötü ki neredeyse kaydırma bile yapamıyorum.