SQL靶场通关记

Less-1[联合查询]:

打开如图,由提示试输入id:

注意:空格不会影响闭环

由下方sql执行知道用表为users,mysql内查询知列数为3,id个数为14,联合传参后发现无正确回显:

这里的–+起什么作用?

我们可以来看看这里查询逻辑的代码:

select * from users where id='$id' limit 0,1
我们在确定id值后需要加入攻击代码,这时要想办法注释原代码$id后面的顿号来确保攻击代码正常被执行,选择合适的注释方式就好,在URL栏内+会被解码为空格,所以本质上–+是使用了两个横杠加空格的单行注释方法

为什么需要符合表要求的id值才能进行注入:

同样的我们看看题目的查询逻辑,只有当id值与数据库内表匹配才会执行sql语句,否则返回空查询结果且后面的语句也不会被执行

将语句在MySQL中执行知合法传参下无法注入:

试非法传参作为注入点:

函数:

  1. LIMIT 函数
    • 语法和基本用法
      • 在 SQL 中,LIMIT是用于限制查询结果返回行数的关键字。语法格式通常为LIMIT [offset], count
      • 例如在 MySQL 数据库中,查询语句SELECT * FROM users LIMIT 5;会从users表中选择前 5 行数据。这里省略了offset(偏移量),默认从第 0 行开始(即结果集的第一行)。
      • 如果想要从结果集的第 3 行开始,取 2 行数据,可以使用SELECT * FROM users LIMIT 3, 2;。其中3是偏移量,表示从第 3 行开始(索引从 0 开始),2是要返回的行数。
    • 用途
      • 优化查询性能:当处理大型数据集时,只获取需要的数据量可以减少数据库的负载,提高查询速度。例如,在一个包含数百万条记录的用户表中,如果只需要显示前 10 条用户信息用于页面展示,使用LIMIT 10可以避免查询和传输整个表的数据。
      • 分页功能:在 Web 应用程序中,用于实现分页效果。例如,每页显示 20 条记录,第一页可以使用LIMIT 0, 20(从第 0 行开始取 20 行),第二页使用LIMIT 20, 20(从第 20 行开始取 20 行),以此类推。
  2. GROUP_CONCAT 函数
    • 语法和基本用法
      • GROUP_CONCAT函数是一种聚合函数,主要用于将分组后的字符串列值连接成一个字符串。语法为GROUP_CONCAT([DISTINCT] expr [,expr...][ORDER BY {unsigned_integer | col_name | expr} [ASC|DESC] [,col_name...]][SEPARATOR str_value])
      • 在 MySQL 中,假设存在一个orders表,包含customer_idproduct_name列。如果想要按照customer_idproduct_name进行分组连接,可以使用SELECT customer_id, GROUP_CONCAT(product_name) FROM orders GROUP BY customer_id;

使用gruop_concat函数与schema库完成注入:

Less-2-Less-4:

第一关基本一致,但要注意第二关是基于数字型的 SQL 注入。与字符型注入不同,数字型注入不需要处理单引号或双引号的闭合问题,也就不需要测闭环方式。

Less-5-Less-10[布尔盲注]:

打开题目及源码发现不存在报错回显:

由于不存在回显,故以\测闭环方式不可行,选择布尔盲注

易知在错误传参后不会显示’you ‘re in‘,于是选择and 连接一个必错条件如1=2,发现无异常说明and 后部分未被执行,盲注得知闭环方式为:’

ascii函数:

是一个用于获取指定字符的 ASCII 码值的函数。它接受一个字符作为输入参数,然后返回该字符对应的 ASCII 码值

例:

SELECT ASCII(char_column) FROM test_table;

获取该字段中每个字符的 ASCII 码值。

注意;

ASCII函数通常要求输入的是单个字符,如果传入多个字符的字符串,不同的数据库系统可能会有不同的处理方式,可能会只取第一个字符进行计算,或者返回错误。

大写字母:ASCII码值>65 <90

小写字母: >97 <122

length函数:

用以返回字符串长度

例;select length (‘Ron’);

回显字符’Ron‘的长度

substring函数:

用于从一个字符串中截取指定长度的子字符串。它可以根据指定的起始位置和长度,从原始字符串中提取出一部分作为新的字符串。

例:select substr(’字符串‘,从第位开始,需要截几位);

select substr(’1234‘,2,2)

输出结果:23

由于不存在回显,需要爆破获得数据库名与表名,此时需要ASCII函数确定大小写,length函数可确定数据库长度,测得长度为8,首字母为S:

用burp爆破数据库长度与名称:

burp抓包后在intruder模块中标记length结果并在爆破后查看响应长度不同的8即为数据库长度:

以同样的方法在burp中用ascii函数爆破出数据库名:security

注意由于有两个参数所以选择集束炸弹(Clusterbomb)

if函数(时间盲注):

一种条件判断函数,用于根据条件表达式的结果返回不同的值。

例句;if(’条件‘,’如果为真则执行’,’如果为假则执行’)

在Less-8中,测出闭环方式后可以使用if函数爆破数据库长度与名称:

使用burp方法同理,但由于burp中不显示响应时间,使用较困难,可以使用py脚本

updatexml函数(报错注入):

例句:select updatexml(1,concat(‘!’,(SQL语句),’!’),1)

例如:select updatexml(1,concat(‘!’,(select database()),’!’),1)

该语句中的1,!并非硬性要求,但需要一直且必定报错,concat函数连接三字符串会在前后两字符串报错情况下输出中间字符串结果,如上句输出结果为: ‘!security!’

Less-11-Less12[post传参,联合查询]:

打开发现是post传参,判断是否有注入:

为什么是 ‘or’而不是之前的‘and’?

从源码入手,可知在输入’后完成闭环,此时id值为空,若用and则必定报错,切记不能简单理解成:Get用and,Post用or:

理解之后步骤与之前类似,以order by语句得出字段数为2,联合查询得显错位为2,库名为security,表名为emails:

’ or 1=1 order by 2 – qwe

‘ union select 1,database() – qwe

‘union select 1,table_name from information_schema.tables where table_schema=’security’ – qwe

回显方式:

11:’ 12: “) 13: ‘) 14: “

Less-13-Less-14[报错注入]

这题特点在于无回显而有报错,故用updatesml函数得到库名为security,表名为emails,列名为id:

‘) and updatexml(1,concat(0x7e,(select database()),0x7e),1) – qwe

‘) and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=’security’ limit 0,1),0x7e),1) – qwe

‘) and updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_schema=’security’ and table_name=’emails’ limit 0,1),0x7e),1) – qwe

Less-15-Less-16:[布尔盲注]

这题特点在于无报错,故报错注入不可行,尝试用盲注:

1
' or length(database())=8 -- qwe

ascii函数可验证库名:security,用burp爆破亦可,同样的方法还可用于测表名:emails,字段名:id

闭环方式:15:’ 16:”)

Less-17:[报错注入]

打开发现提示要重置密码,正常测试是否存在注入如图:

得知注入点在’New Password‘处:使用updatexml函数得库名:

‘ and updatexml(1,concat(0x7e,(select database()),0x7e),1) – qwe

接下来用与Less-13的方法得到表名:emails 列名:id


SQL靶场通关记
https://sujohn-ron.github.io/2026/07/20/SQL靶场通关记/
作者
SancyZyW0o
发布于
2026年7月20日
许可协议