2 puan yazan GN⁺ 2024-05-26 | 1 yorum | WhatsApp'ta paylaş
  • Go’nun checksum database’i ve public module proxy’si, Go kodu içermeyen depoları bile kabul edebildiği için, rastgele Git deposu verilerini Go altyapısına yükleyip sonra yeniden indirmek için bir yol oluşuyor
  • sum.golang.org/lookup/$module@$version isteği, kayıt altına alınmamış bir modül sürümüyle karşılaştığında bunu kaynak sunucudan alıyor; bu süreçte ilgili depo zip’i proxy.golang.org üzerinde de sunuluyor
  • Homebrew’ün Ruby deposu ve bir Rust deposu fork’u checksum database’te yer alıyordu; deneylerde yalnızca yeni Go modüllerinin değil, Go dosyası içermeyen depoların da pseudo-version ile kaydedilebildiği başarıyla gösterildi
  • Modül zip’leri için hem sıkıştırılmış hem sıkıştırılmamış durumda azami 500 MiB sınırı var; ancak bu ölçek, geliştirici makineleri ve CI/CD’deki indirme kısıtlarını aşmak, payload depolamak ve C2 uygulamak için yeterince büyük
  • sum.golang.org üzerindeki yaklaşık 1,59 milyon benzersiz yolun yaklaşık 1,51 milyonu GitHub yolu; bu da %95 düzeyinde olup Go ekosisteminin GitHub’a bağımlılığını ve public proxy’nin kötüye kullanılma olasılığını birlikte ortaya koyuyor

Go checksum database’inde bulunan Go dışı depolar

  • Go’nun checksum database’i incelenirken modules tablosunda github.com/homebrew/homebrew-core’un çok sık göründüğü fark edildi
    • github.com/homebrew/homebrew-core: 39.438 adet
    • github.com/Homebrew/homebrew-core: 30.896 adet
    • github.com/concourse/concourse: 25.372 adet
    • github.com/openshift/release: 24.065 adet
    • github.com/cilium/cilium: 22.138 adet
  • Homebrew deposunun Ruby kullandığı biliniyor; depoda ve klonlanan dosyalarda go.mod ya da Go kaynak dosyası bulunamadı
  • Büyük/küçük harf farkı, Go dokümantasyonundaki case encoding kuralıyla açıklanıyor
    • Büyük harfler ! ve karşılık gelen küçük harfle kodlanıyor; böylece büyük/küçük harf duyarsız dosya sistemlerinde bile example.com/M ve example.com/m birlikte saklanabiliyor
  • github.com/Edu4rdSHL/rust-headless-chrome da Go ile ilgisi olmayan bir Rust deposu fork’u olmasına rağmen checksum database’te görünüyor

/lookup’ın depoyu getirme biçimi

  • Go modül dokümantasyonundaki Go Modules Reference’a göre Go komutu, checksum database’i sorgularken önce /lookup endpoint’inden kayıt verilerini alıyor
  • Modül sürümü henüz log’a kaydedilmemişse checksum database, yanıt vermeden önce ilgili modülü kaynak sunucudan getirmeyi deniyor
  • Endpoint biçimi $base/lookup/$module@$version şeklinde
    • $module için $version’a ait log kayıt numarasını, go.sum satırlarını ve imzalı ağaç açıklamasını döndürüyor
  • github.com/homebrew/homebrew-core’un pseudo-version’ı sorgulandığında checksum kaydı ve go.mod hash’i döndürülüyor
  • Depoda sürüm etiketi yoksa Go’nun pseudo-version kuralları kullanılıyor

Yeni Go modülü kaydetme deneyi

  • Yeni bir Go modülü olan github.com/gdbinit/fluxmatter oluşturulduktan sonra lookup isteğiyle kaydedilip kaydedilmediği kontrol edildi
  • @latest sorgusu, bunun canonical version olmadığına dair hata döndürdü
    • bad request: version "latest" is not canonical
  • @v0.0.0 sorgusu, ilgili revision’ın bilinmediğine dair hata döndürdü
    • not found: ... invalid version: unknown revision v0.0.0
  • Ancak checksum database yeniden eşitlenip sorgulandığında modülün kaydedilmiş olduğu görüldü
    • github.com/gdbinit/fluxmatter|v0.0.0-20240524163826-a7e64ffd69f2|2024-05-24T16:40:51.203837Z
  • proxy.golang.org/github.com/gdbinit/fluxmatter/@latest, pseudo-version ve GitHub kaynak bilgilerini döndürdü; ilgili sürümün zip dosyası da indirilebildi ve sıkıştırma doğrulaması yapılabildi
  • İlk tohumlama için tam sürümü belirtmek gerekmiyor; modül yolu ve sürüme benzer bir değer içeren bir lookup sorgusu tek başına çalışıyor

Go kodu olmayan depolar da public proxy’ye yükleniyor

  • Hiç Go kodu içermeyen github.com/gdbinit/readmem deposuyla da aynı deney başarılı oldu
  • lookup isteği v0.0.0 revision’ının bilinmediğine dair hata döndürdü, ancak checksum database’e pseudo-version ile kaydedildi
    • github.com/gdbinit/readmem|v0.0.0-20131006075740-407cb0a56933|2024-05-24T16:45:35.88456Z
  • proxy.golang.org üzerindeki @latest, ilgili deponun pseudo-version’ını ve Git kaynak bilgilerini döndürdü
  • İndirilen zip’te Go dosyaları değil Entitlements.plist, README, Xcode project dosyaları, main.c gibi dosyalar yer alıyordu
  • Bu deneyde GitHub deposu kullanıldı; ancak çalışan bir VCS varsa başka barındırma sitelerinde de mümkün olabilir

GitHub bağımlılığı ve boyut sınırı

  • Checksum database’teki benzersiz yol sayısı 1.591.375’ti; bunların içinde github.com% yolları 1.515.957 adetti
  • Benzersiz yolların yaklaşık %95’i GitHub’da barındırılıyor {p:95}
  • Bu rakamlar fork’ları veya gerçek Go kodu olmayan hedefleri ayıklamayan ham istatistikler
  • Go modül zip’lerine File path and size constraints uygulanıyor
    • Module zip dosyası en fazla 500 MiB
    • Dosyaların toplam sıkıştırılmamış boyutu da en fazla 500 MiB
    • go.mod dosyası en fazla 16 MiB
    • LICENSE dosyası da en fazla 16 MiB
  • Bu sınır, kullanıcılara, proxy’ye ve modül ekosisteminin diğer bölümlerine yönelik hizmet reddi saldırılarını azaltmaya yarayan bir mekanizma
  • 500 MiB, kötüye kullanım olasılığı düşünüldüğünde yeterince büyük bir boyut

Olası kötüye kullanım senaryoları

  • Public Go proxy, geliştirici makinelerinde veya CI/CD sunucularında hedef indirme kısıtlarını aşmak için kullanılabilir
    • Private GOPROXY bulunmayan bir durum varsayılıyor
    • Zararlı yazılım, payload’u depoya yükleyip gerektiğinde proxy’den indirebilir
    • Kaynak asıl yerinden silinse bile checksum database entry’sinde yalnızca küçük bir iz kalabilir
  • proxy.golang.org’a yönelik DoS’u gerçekleştirmek zor olabilir
    • Proxy’nin rastgele Git depolarını indirmesini istemek mümkün
    • Olası saldırı, çok sayıda GitHub URL’si toplayıp lookup API’sine çok sayıda istek göndermek şeklinde olabilir
    • Sunucu uygulaması bilinmiyor, ancak work queue gibi paralel işlem sınırlamaları olabilir
    • GitHub tarafındaki bant genişliği korumalarının devreye girme ihtimali de var
    • Depolama alanını hedefleyen DoS olasılığı da var, ancak bu sadece tahmin
  • C2(command and control), proxy.golang.org üzerine kolayca kurulabilir
    • @latest sorgusuyla belirli bir modülün en yeni sürümü bulunabilir
    • Payload basit bir dosya da olabilir, go.mod veya Go kaynak dosyası içinde de gizlenebilir
    • Tek bir depo kullanımından kaçınmak için module DGA kullanılabilir

C2 indirme akışı

Sonuç ve kalan sorular

  • Go checksum database’i ve proxy’si, belgelenmiş prosedürlere göre kayıtlı olmayan modülleri kaynak sunucudan getirip saklayabiliyor
  • Mevcut durum Go altyapısında ciddi bir sorun gibi görünmüyor; ancak kolayca kötüye kullanılabilir ve iyileştirme alanı var
  • Go kodu olmayan depoların proxy’ye ve checksum database’e çıkmasına izin verilmesinin belgelenmiş veya kamuya açık olmayan gerekçeleri olabilir
  • Birilerinin bunu hâlihazırda kötüye kullanıp kullanmadığını anlamak için yaklaşık 1,6 milyon benzersiz depo ve en güncel yerel database’e göre yaklaşık 22 milyon entry incelenmeli
  • Bazı geçerli non-Go projelerin neden database’te bulunduğu hâlâ açık bir soru olarak duruyor

1 yorum

 
GN⁺ 2024-05-26
Hacker News görüşleri
  • Kullanıcıların veri yüklediği ve bu verilerin herkese açık göründüğü çevrimiçi servisler, eninde sonunda komuta-kontrol, telif hakkı ihlali ve CSAM barındırma için kullanılıyor
    Dosya barındırma dışında da önemli kullanım alanları olduğu için engellenmesi zor servislerde bu özellikle geçerli; Twitter[1], Telegram[2] ve PGP anahtar altyapısında[3] daha önce yaşandı, GitHub gibi bariz hedefleri saymaya bile gerek yok
    [1] https://pentestlab.blog/2017/09/26/command-and-control-twitt...
    [2] https://www.blazeinfosec.com/post/leveraging-telegram-as-a-c...
    [3] https://torrentfreak.com/openpgp-keyservers-now-store-irremo...

    • Gmail, Google Groups, Google Drive ve Gchat için de durum aynıydı; depolanan verilerin herkese açık olması bile gerekmiyordu
      Gmail örneğinde, kimlik bilgileri dağıtılıp kullanıcıların giriş yapması sağlanıyor, ardından IMAP üzerinden yüklenmiş ek dosyalar okutuluyordu
      Eski bir Google SAD-SRE (Spam, Abuse, Delivery) çalışanıydım
    • PyPI de paketlere rastgele Python dışı dosyalar koymaya izin verdiği için bu amaçla kullanılmaya uygun görünüyor
      Bir dosyayı Base64 ile kodlayıp Python kodu dizgesi içine koymak da mümkün
    • Daha önce kullanıldı mı bilmiyorum ama daha az obvious hedef HuggingFace gibi görünüyor
  • Googler’ım; bunlar kişisel görüşlerim ve bu alanı iyi bilmiyorum
    Go ekibinin GCP ve Drive tarafıyla birlikte çalışmış olmasını umuyorum; çünkü kötü amaçlı dosya barındırma, Google’ın sürekli uğraştığı bir sorun
    Google’ın insanların rastgele veri koymasına zaten izin verdiği diğer endpoint’lerden çok da farklı değil

    • Eski bir Googler’ım ve Go Dev Tools ekibini pek tanımıyorum; ancak Google, çalıştığım ya da yakın arkadaşlarımdan duyduğum büyük şirketler arasında bu tür şirket içi iş birliğini neredeyse en iyi yapanlardan biri
      Google, altyapıyı merkezi ekiplerin yönetip şirket geneline paylaştırması konusunda çok başarılı. Mesajlaşma uygulamaları hariç böyle; tamamen tahmin yürütüyorum ama Go ekibi muhtemelen dahili blob depolama kullanıyordur ve kötüye kullanım müdahalesiyle dosya taramasını otomatik yapan dahili bir altyapı ekibi de vardır diye düşünüyorum
  • PyPI’da da epey Python dışı proje var
    Python’da kullanıcılar kütüphane kodunu derleyemeyebileceği için derlenmiş ikili dosya olan wheel dağıtma yeteneğine ihtiyaç var
    Bu tür kodlar çoğunlukla C ile yazılıyor ama Golang[1] da mümkün; örnek bulamadım ama bunun kütüphane değil, uygulama dağıtımı için de kullanıldığını gördüğümü sanıyorum
    C ile bir uygulama yazıp PyPI’a koymak ve kullanıcılara pip install ile kurmalarını söylemek oldukça hoş
    [1] https://github.com/popatam/gopy_build_wheel_example

    • Örneğin Python kullanma şartı getirseniz bile, kötü niyetle buna uymaya çalışan birinin yalnızca asgari düzeyde Python stub kodu sağlaması yeterli olmaz mı diye düşünüyorum
      Linux’ta ls komutunun Python ile yazılmış sayılması gibi olur; bu tür oyunlara girmemek daha iyi gibi
    • pip bir paketi indirmek için venv/virtualenv/pipenv/pyenv gibi bir ortam içinde olunmasını şart koşmadan önce, bu kullanım çok daha faydalı olurdu gibi geliyor
    • pip install cmake de var; tescilli ikili dosyalar da pip install nvidia-cudnn-cu12 gibi mümkün
    • Son zamanlarda PyPI’ı FFmpeg ve Eigen gibi Python dışı araçlar için çok kullanıyorum
      Homebrew’den tamamen vazgeçebilmemin nedenlerinden biri de bu oldu
  • Safça düşünüyor olabilirim ama bunun GitHub deposuna dosya yüklemekten nasıl farklı olduğunu anlamıyorum
    Tek fark GitHub’da hesap oluşturmak gerekmesi mi? GitHub’a da rastgele veri depolanabiliyor ve 500MB sınırı da yok

    • GitHub’ın anonim isteklere yönelik oldukça sıkı istek limitleri var
  • CUE’nun modül sistemi nihayet çıkıyor; MVS Go’ya benziyor ama OCI altyapısı üzerine inşa edilmiş
    Bağımlılık yönetim sistemleriyle ilgileniyorsanız bakılacak bağlantılar şunlar
    proposal: https://github.com/cue-lang/proposal/tree/main/designs/modul...
    custom registry: https://cuelang.org/docs/tutorial/working-with-a-custom-modu...
    road map: https://github.com/orgs/cue-lang/projects/10/views/8
    0.9.0-alpha-5’ten itibaren modüller varsayılan olarak etkin: https://github.com/cue-lang/cue/releases/tag/v0.9.0-alpha.5
    Go Sum’da şeffaflık günlüğünü Trillian projesi destekliyor: https://github.com/google/trillian
    CUE, attestation gibi OCI seçeneklerinin üzerine oturmayı planlıyor

    • Bunun bağlantısı verilen yazıyla ne ilgisi olduğunu anlamadım
  • golang proxy ve sumdb'den yararlanarak, daha doğrusu bunları kötüye kullanarak, keyfi URL'lerin sağlama toplamları için ücretsiz bir şeffaflık günlüğü oluşturma fikriyle biraz oynadım
    https://getsum.pub/

  • Aptalca düşünüyor olabilirim ama burada tam olarak sorunun ne olduğunu anlamıyorum
    Proxy'nin Go dışı depoları önbelleğe alması biraz israf olabilir, ama bunu yapmasa bile Go depolarını önbelleğe aldırarak zaten keyfi veri depolatmak mümkün değil mi?
    Bir şeyi kaçırmıyorsam kulağa tamamen önemsiz bir şey gibi geliyor

    • Bir şeyi kaçırdığını sanmıyorum
      Buradaki yeni haber, güvenliği olmayan herkese açık bir proxy'nin proxy'leyeceği şeyi alıp güvenliği olmayan bir biçimde herkese sunması gibi görünüyor
      Yazıda, bazı izlenen ağların rastgele web URL'lerine kıyasla golang proxy URL'lerine daha fazla güvenebileceği ve bunun itibar filtresini aşmak gibi amaçlarla kullanılabileceği söyleniyor; ama bunun için zaten pek çok yöntem var ve bu yöntem özel görünmüyor
  • Konu dışı ama alan adını görünce kelime oyunu uğursuz geldi, bu yüzden put.as'a baktım; büyük ölçüde beklediğim şey çıktı

    • https://put.as/ biraz NSFW
    • İş yerinde onu açma hatasına düştüm
    • İspanyolcada çoğul bir kelime aslında. Ama…
  • Zaten bilinen bir sorun: https://github.com/golang/go/issues/31866

    • Bu düzeltme yanlışlıkları önlemeye yardımcı olur, ama bunu bilerek yapmak isteyen biri köke .mod ve .go dosyaları ekleyemez mi?
    • Marwan'ın bu issue'da yer alması hiç şaşırtıcı değil
      O ve Aaron Athens'i yaptı; bildiğim kadarıyla Marwan, Athens'in temelini oluşturan ilk Go indirme protokolü implementasyonunu yazdı
      Bu issue'yu ilginç kılan şey, Athens'in modül doğrulaması için ön kontrol olarak bahsedilen go mod download -json komutunu zaten kullanması
      Genel olarak bir depo, Go modül komutunun anladığı bir modül olarak geçerse Athens onu sunar
      Daha yasaklı bir ifadeyle söylersek, modül sürümü, sözde sürüm ve +incompatible oluşturabiliyor olmanız; ayrıca o modülün ve bağımlılıklarının geçerli bir sağlama toplamı üretmesi gerekir
      Modül sağlama toplamı şu anda .mod dosyası ve tüm dosyalarla, ayrıca her bağımlılığı özyinelemeli olarak içermekle ilgili
      Bu yüzden yazarın söylediği gibi, temel bir Go programınız varsa tasarım gereği keyfi dosyalar için bolca alanınız olabilir
  • W3C, web'deki her şeyin güçlü biçimde önbelleğe alınabilmesi için zemini hazırladı; buna rağmen genel amaçlı proxy cache sayısının bu kadar az olması tuhaf
    Yayıncılar gerekmediği halde kısa Cache-Control: max-age ya da Vary: Cookie yanıtları mı gönderiyor?
    ISP'ler peering yerine transit için çok mu fazla ödüyor?

    • Genelde cache'in içeriği değiştirmediğini garanti etmenin bir yolu yok
      Örneğin HTTPS olmayan sitelerde ISP proxy'si reklam enjekte edebilir
      Yazılım indirmelerinde genellikle imza ve sağlama toplamı olur, ama rastgele içerikte bunlar pek bulunmaz