Go altyapısının kötüye kullanılması
(reverse.put.as)- 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@$versionisteğ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’iproxy.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
modulestablosundagithub.com/homebrew/homebrew-core’un çok sık göründüğü fark edildigithub.com/homebrew/homebrew-core: 39.438 adetgithub.com/Homebrew/homebrew-core: 30.896 adetgithub.com/concourse/concourse: 25.372 adetgithub.com/openshift/release: 24.065 adetgithub.com/cilium/cilium: 22.138 adet
- Homebrew deposunun Ruby kullandığı biliniyor; depoda ve klonlanan dosyalarda
go.modya 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 bileexample.com/Mveexample.com/mbirlikte saklanabiliyor
- Büyük harfler
github.com/Edu4rdSHL/rust-headless-chromeda 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
/lookupendpoint’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$moduleiçin$version’a ait log kayıt numarasını,go.sumsatı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ı vego.modhash’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/fluxmatteroluşturulduktan sonralookupisteğiyle kaydedilip kaydedilmediği kontrol edildi @latestsorgusu, bunun canonical version olmadığına dair hata döndürdübad request: version "latest" is not canonical
@v0.0.0sorgusu, 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/readmemdeposuyla da aynı deney başarılı oldu lookupisteğiv0.0.0revision’ının bilinmediğine dair hata döndürdü, ancak checksum database’e pseudo-version ile kaydedildigithub.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.cgibi 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.moddosyası en fazla 16 MiBLICENSEdosyası 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
GOPROXYbulunmayan 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
- Private
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
lookupAPI’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@latestsorgusuyla belirli bir modülün en yeni sürümü bulunabilir- Payload basit bir dosya da olabilir,
go.modveya Go kaynak dosyası içinde de gizlenebilir - Tek bir depo kullanımından kaçınmak için module DGA kullanılabilir
C2 indirme akışı
- Bir implant’ın komut alması için şu adımları izlemesi yeterli
https://proxy.golang.org/module_path/@latestisteği- JSON sonucundan pseudo-version veya version çıkarma
https://proxy.golang.org/module_path/@v/version.zipisteğiyle zip indirme- Zip içeriğini açıp komutu parse etme
- Bu akış, Go kodunda 300 satırdan az bir uygulamayla gerçekleştirilebilecek kadar basit
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
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 ö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
Bir dosyayı Base64 ile kodlayıp Python kodu dizgesi içine koymak da mümkün
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
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 installile kurmalarını söylemek oldukça hoş[1] https://github.com/popatam/gopy_build_wheel_example
Linux’ta
lskomutunun Python ile yazılmış sayılması gibi olur; bu tür oyunlara girmemek daha iyi gibipipbir 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 geliyorpip install cmakede var; tescilli ikili dosyalar dapip install nvidia-cudnn-cu12gibi mümkünHomebrew’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
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
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/
Sadece herkese açık bir şeffaflık günlüğü istiyorsanız sigstore projesinin herkese açık rekor instance'ı çok daha uygun
https://www.sigstore.dev/
https://docs.sigstore.dev/logging/overview/
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
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ı
Zaten bilinen bir sorun: https://github.com/golang/go/issues/31866
.modve.godosyaları ekleyemez mi?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 -jsonkomutunu 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
+incompatibleoluşturabiliyor olmanız; ayrıca o modülün ve bağımlılıklarının geçerli bir sağlama toplamı üretmesi gerekirModül sağlama toplamı şu anda
.moddosyası ve tüm dosyalarla, ayrıca her bağımlılığı özyinelemeli olarak içermekle ilgiliBu 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-ageya daVary: Cookieyanıtları mı gönderiyor?ISP'ler peering yerine transit için çok mu fazla ödüyor?
Ö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