ClickHouse多個漏洞原理分析

發布時間 2022-03-21

一、漏洞概述


ClickHouse是俄羅斯yandex公司于2016年開源的云數據庫管理系統,ClickHouse廣泛應用于云平臺的大數據分析應用中,其用戶包括uber、ebay、德意志銀行、阿里巴巴、騰訊等。


近日,JFrog安全研究團隊披露了在ClickHouse DBMS中發現的7個漏洞,擁有ClickHouse最低權限的攻擊者可以通過這些漏洞使ClickHouse服務器崩潰、泄漏內存內容,甚至導致遠程代碼執行(RCE)。

漏洞影響了ClickHouse 21.10.2.15版本之前的所有版本。具體漏洞描述如下表所示:


圖片1.png


二、處置建議


2021年10月18日發布的ClickHouse 21.10.2.15版本修復了上述的7個漏洞,請盡快升級到ClickHouse 21.10.2.15及以后的版本。


下載鏈接:

https://github.com/ClickHouse/ClickHouse/releases/


緩解措施:

如果無法升級,請在服務器中添加防火墻策略,限制只允許特定IP的客戶端訪問WEB端口(8123)和TCP服務器端口(9000)。


三、漏洞分析


這些漏洞都存在ClickHouse Server處理壓縮數據的請求處理過程中,ClickHouse Server支持對用戶請求的附帶數據進行壓縮。用戶可以在發起WEB請求時,將decompress標志設為1即可,舉例如下:

cat query.bin | curl -sS —data-binary @-‘http://serverIP:8123/?user=xxx&password=xxx&decompress=1' 

查詢的附帶數據(query.bin)可以按下面的結構進行組織:


圖片2.png


ClickHouse支持多種壓縮格式,包括LZ4、Gorilla、Delta等多種壓縮算法。ClickHouse Server根據請求中附帶數據的壓縮算法標識,調用不同的解壓算法來對數據進行解壓。


3.1 LZ4算法介紹


LZ4壓縮算法是LZ算法系列中的一種,也是目前綜合效率最快的壓縮算法之一。

一個LZ4壓縮塊由多個LZ4序列組成,LZ4序列由以下數據構成,如下圖所示:


圖片3.png

Token大小為1字節,高4個bits為不可壓縮數據(literal)的長度(literallength),而低4個bits為可以壓縮數據(match)長度(match length)。如果literallength的值為0,則表示后續數據里沒有literal。由于literal length只有4比特來表示,它的最大值為15。當literal數據的大小大于等于15時,需要在Token字段后添加格外的字節來表示literal的長度(Literal length+)。


如果match length的值為0,則表示后續數據里沒有match。由于matchlength只有4比特來表示,它的最大值為15。當match數據的大小大于等于15時,需要在offset字段后添加格外的字節來表示match的長度(match length+)。

Literals指沒有重復、首次出現的字節流,即不可壓縮的部分。

Offset指的是現在字符串離它的匹配項的長度,而匹配長度指的是現在字符串與字典中相同字符串的匹配長度。offset占用2個字節,即最大值為65535。

Match指重復項,可以壓縮的部分。


 3.2 CVE-2021-43304原理

src/Compression/LZ4_decompress_faster.cpp的decompressImpl函數在拷貝LZ4序列數據的literal時,沒有判斷復制的數據是否超過目標緩沖區的限制。當需要復制的數據超過目標緩存的大小時,會導致堆溢出。


圖片4.png


如上圖代碼所示,ip是指向壓縮緩沖區的指針。op是指向分配的目標緩沖區的指針,該目標緩沖區的大小為報頭中給定的解壓大小。copy_end是指向復制區域末端的指針。


copy_amount是模板的參數,可以是8、16或32。復制區域被分塊復制,每個塊的大小都與復制量相同。

攻擊者可以構造惡意的LZ4序列數據,其中litera的長度(length變量)大于dest_size,將導致堆溢出。


3.3 CVE-2021-43304漏洞復現

我們可以構造這樣的請求數據,其中壓縮算法為LZ4,literal的長度為255*200,而dest_size為1。由于literal的大小遠大于解壓后緩沖區的大小,當clickhouse_server進行復制操作時將導致堆溢出,觸發程序崩潰。


圖片5.png


3.4 CVE-2021-43305漏洞原理


漏洞存在src/Compression/LZ4_decompress_faster.cpp的decompressImpl函數中,該函數直接從LZ4壓縮數據中讀取16位無符號偏移量(offset攻擊者可以控制),offset用于定位match數據的位置,當offset的值大于dest_size的值時,copyOverlap操作將導致堆溢出。


圖片6.png


3.5 CVE-2021-42388及CVE-2021-42387漏洞原理


漏洞存在src/Compression/LZ4_decompress_faster.cpp的decompressImpl函數中,該函數直接從LZ4壓縮數據中讀取16位無符號偏移量(offset攻擊者可以控制),該偏移量用于計算wildCopy操作的源數據地址。當offset的值為大于copy_amount時(如offset = 0xffff),將導致程序將op地址之前的數據拷貝到op指向的地址中,從而導致越界讀。


圖片7.png


CVE-2021-42387是CVE-2021-42388的一個類似漏洞,這里就不再介紹。


3.6 CVE-2021-42389、CVE-2021-42390、CVE-2021-42391漏洞原理

ClickHouse支持的DoubleDelta編解碼器、Delta編解碼器、Gorilla編解碼器中都存在被零除的漏洞。它們基于將壓縮緩沖區的第一個字節設置為零。解壓代碼讀取壓縮緩沖區的第一個字節,并對其執行模運算以獲得剩余字節,當source[0]為0時,CPU對0進行取模時操作將發生除0異常。


圖片8.png


四、結束語


大數據時代下,大量數據聚集、連接及網絡邊界的延伸都為數據庫的的安全提出了更高的要求。數據庫作為信息技術系統的核心和基礎,承載著越來越多的關鍵業務系統,成為企業和機構最具有戰略性的核心數據資產,因此數據庫方面的安全值得我們持續關注。


參考鏈接:

[1]https://jfrog.com/blog/7-rce-and-dos-vulnerabilities-found-in-clickhouse-dbms/

[2]https://github.com/ClickHouse/ClickHouse

[3]https://thehackernews.com/2022/03/multiple-flaws-uncovered-in-clickhouse.html