nepctf 2025 sql注入 我难道不是sql注入天才吗

看到表的字段名 id name email age

输入' 报错看到查询语句 select * from users where id =
得到表名是user
题目提示
后端数据库是clickhouse,黑名单字符串如下preg_match('/select.*from|\(|or|and|union|except/is',$id)
测试了一下

用不了&&
这样直接的报错注入好像不行了。直接的布尔注入也不行。然后过滤了select 任意 from 。而且union也不行。这样的话。大脑枯竭了。去查资料了。
我们注入的位置是条件的的地方。可以看看填完条件后要拼接什么。以前的话union 的话看看能不能有别的替代。
INTERSECT 子句 | ClickHouse Docs

虽然是看了别人的wp知道intersect但是现在是复现,我不管,以后我肯定能自己找到的
很好又找到了个
except ,但是也被过滤了
这个好刚好是在where 后面是intersect。

然后要求是要列相同
看看用法吧。

就是前一个查询和后一个查询的交集。我们的前一个查询是 select * from user ,前面得知有四个列 id name email age 。所以后面也要有四个列。想想咋构造呢。select * from user intersect
。。。。。。。。 但是不能用select from 。看看有没有替代select from 但是要能返回结果集的,因为intersect要取交集。不想找了,看下wp。
id INTERSECT FROM system.databases AS inject JOIN users ON inject.name LIKE '{pattern}' SELECT users.id, users.name, users.email, users.age
为啥我看不懂,intersect后面加from是啥
无意间发现

666 。这意思是select * from table 和 from table select * 是一样的。看来要关注数据库新特性。
但是好像搜不到啊。我总不能看完整个文档吧。算了遇到就算记住了。clickhouse特性。。。。
那注入语句的意思就是
id INTERSECT SELECT users.id, users.name, users.email, users.age FROM system.databases AS inject JOIN users ON inject.name LIKE '{pattern}'
嗯,system.databases是什么呢

system是数据库,里面有个表 system.databases 有数据库名,应该是用来爆库名的。
继续分析注入语句
id INTERSECT SELECT users.id, users.name, users.email, users.age FROM system.databases AS inject JOIN users ON inject.name LIKE '{pattern}'
as
查询时给列或计算结果起别名,让返回的结果列名更易读。
语法:列名/表达式 AS 别名。
这里就是给system.databases 取别名,别名是inject
join...on...
未指定类型的JOIN默认为INNER
一、JOIN 的核心目的
将多个表中 “相关联的数据” 合并成一个结果集。例如:
users表存储用户基本信息(id, name);orders表存储订单信息(order_id, user_id, amount);
通过user_id关联两表,可得到 “每个用户的订单详情”。
二、JOIN ... ON 的基础语法
SELECT 列名列表
FROM 表1
JOIN 表2
ON 表1.关联字段 = 表2.关联字段;
JOIN:指定要关联的表(表2);ON:紧跟关联条件(两表中哪个字段相等才能关联)。
三、常见 JOIN 类型(与 ON 配合)
ClickHouse 支持多种 JOIN 类型,核心区别在于 “如何处理不满足关联条件的数据”:
1. INNER JOIN(默认,可省略 INNER)
只保留两表中都满足关联条件的数据行。
在 ClickHouse 中,LIKE 是用于字符串模糊匹配的运算符,主要功能与标准 SQL 中的 LIKE 一致,用于判断一个字符串是否符合指定的模式。它常与通配符配合使用,在数据查询和 SQL 注入场景中都非常常见。
然后是like
一、LIKE 的基础语法
字符串列 LIKE '匹配模式'
- 若字符串符合 “匹配模式”,返回
1(True); - 若不符合,返回
0(False)。
二、关键通配符(与模式匹配规则)
LIKE 的核心能力来自通配符,ClickHouse 支持两种常用通配符:
1. %(百分号):匹配任意长度的字符(包括 0 个字符)
- 示例:
'abc' LIKE 'a%'→1(以a开头,后面可以是任意字符);'abc' LIKE '%c'→1(以c结尾,前面可以是任意字符);'abc' LIKE '%b%'→1(中间包含b);'abc' LIKE 'd%'→0(不匹配)。
2. _(下划线):匹配单个任意字符(必须有且仅有一个字符)
- 示例:
'abc' LIKE 'a_c'→1(a开头,c结尾,中间是 1 个任意字符);'ab' LIKE 'a_'→1(a开头,后面是 1 个任意字符);'abc' LIKE 'a__'→1(a开头,后面是 2 个任意字符);'abc' LIKE 'a_'→0(长度不匹配,需要 1 个字符但实际有 2 个)
分析注入语句
id INTERSECT SELECT users.id, users.name, users.email, users.age FROM system.databases AS inject JOIN users ON inject.name LIKE '{pattern}'
这里的 FROM 后面是 “表连接结构”(主表 + 关联表)
意思就是连接user表和system.databases表,user表是当前数据库的表就是最开始发现的表名,里面的字段是id name email age。system.databases里面存的是数据库信息,里面有个字段是name,存的是库名。
条件是两个表的system.databases.name相同,system.databases.name就是库名。
那意思就是,连接两个表的条件是当前的数据库名一样。然后user表的。。。
来个ai解释吧。我死了。。。。。
-
右侧查询:
FROM system.databases AS inject JOIN users ON inject.name LIKE '{pattern}'这是整个 payload 的 “条件开关”,决定右侧查询是否返回数据:
system.databases AS inject:从 ClickHouse 系统表system.databases(存储所有数据库名)取数据,别名inject方便后续引用。JOIN users ON inject.name LIKE '{pattern}':JOIN users:将system.databases表与users表(应用程序的用户表)进行内连接(仅保留匹配的行)。- 连接条件
inject.name LIKE '{pattern}':只有当system.databases.name(数据库名)匹配{pattern}(猜测的字符模式,如nep%、NepCTF{%)时,连接才会成功,此时右侧查询会返回users表的真实数据(如包含User_5的用户记录)。
其实大体来看的话两select语句取交集,前面的字段是一样的,from后面不一样。然后第一个select是from user,第二个是表连接结构(user+ )。。。。。写不了一点。。。。
换个思路,当inject.name 和pattern 匹配后,就会
在 FROM system.databases AS inject JOIN users ON inject.name LIKE '{pattern}' 这句代码中,ON 后面的 inject.name LIKE '{pattern}' 是一种特殊的 “关联条件”—— 它并不要求两表的字段 “相等”,而是通过 LIKE 模糊匹配来决定两表是否关联。这种设计是为了在盲注中实现 “用猜解的模式控制关联结果”,具体可以从以下角度理解:
一、表面逻辑:两表如何 “关联”?
-
system.databases AS inject:这是 “左表”,来自 ClickHouse 的系统表,存储所有数据库的名称(inject.name即数据库名)。 -
users:这是 “右表”,是应用程序的用户表(假设存在,存储用户信息)。 -
ON inject.name LIKE '{pattern}':关联条件是 “左表的name字段(数据库名)是否匹配{pattern}(猜解的模式)”。这里的 “关联” 本质是:当
inject.name符合{pattern}时,system.databases表和users表就会产生 “虚拟关联”,此时JOIN后的结果会包含users表的数据;如果不匹配,两表无关联,JOIN结果为空。
二、特殊之处:不比较两表字段,只判断单表条件
常规的 JOIN ON 是比较两表的字段(如 ON a.id = b.user_id),而这里的 ON 条件只涉及左表(system.databases)的字段 inject.name,与右表(users)的字段无关。
这相当于:
“只要 system.databases 表中存在符合 {pattern} 的数据库名,就把 users 表的所有数据拿出来;否则,什么都不拿。”
id INTERSECT SELECT users.id, users.name, users.email, users.age FROM system.databases AS inject JOIN users ON inject.name LIKE 'nepnep'
SELECT 字段列表 FROM 表A INNER JOIN 表B on 1
SELECT 字段列表 FROM 表A INNER JOIN 表B ON 1 是一种特殊的内连接写法,其中 ON 1 是一个恒真条件(在 SQL 中,非 0 数值表示 “真”),这会导致两表进行无条件内连接,产生特殊的结果集。以下是详细解析:
一、核心逻辑:ON 1 是什么?
ON 1 等价于 ON TRUE,表示关联条件永远成立。因此,表 A 和表 B 的内连接会忽略两表的实际字段关系,强制将两表的所有行进行组合。
二、执行结果:两表的 “笛卡尔积”
当 ON 条件恒真时,内连接的结果是表 A 和表 B 的笛卡尔积(Cartesian product):
- 若表 A 有
M行,表 B 有N行,结果会有M × N行; - 每一行是表 A 的一行与表 B 的一行的组合(所有可能的配对)。
这是相当于把条件变成要么0要么1了吗,那这样爆破对的话就返回1,就把 users 表的所有数据拿出来,然后和前面的select取交集就会返回数据,相当于bool注入;否则,什么都不拿,就是0就不会返回结果,交集就是0,就不会返回数据。剩下的payload就是爆破表和列和值了。
补张system的图,test_database是我自己建的数据库。

更多推荐



所有评论(0)